Copepod Collection

Copepods were collected at approximately weekly intervals from Lake Champlain (Burlington Fishing Pier). Plankton was collected from the top 3 meters using a 250 um mesh net.

# # Lake Champlain near Burlington, VT
# siteNumber = "04294500"
# ChamplainInfo = readNWISsite(siteNumber)
# parameterCd = "00010"
# startDate = "2023-01-01"
# endDate = "2024-5-20"
# #statCd = c("00001", "00002","00003", "00011") # 1 - max, 2 - min, 3 = mean
# 
# # Constructs the URL for the data wanted then downloads the data
# url = constructNWISURL(siteNumbers = siteNumber, parameterCd = parameterCd,
#                        startDate = startDate, endDate = endDate, service = "uv")
# 
# raw_temps = importWaterML1(url, asDateTime = T) %>%
#   mutate("date" = as.Date(dateTime),
#          "hour" = hour(dateTime)) %>%
#   select(dateTime, tz_cd, date, hour, degC = X_00010_00000)
# 
# temp_data =  raw_temps %>%
#   select(date, hour, "temp" = degC)
# 
# write.csv(temp_data, file = "./Output/Data/champlain_temps.csv", row.names = F)

Collections began in late May 2023. Several gaps are present, but collections have continued at roughly weekly intervals since then. Copepods from 48 collections were used to make a total of 1312 thermal limit measurements. Over this time period, collection temperatures ranged from 2.5 to 26.5°C.

There is substantial variation in thermal limits across the species collected. There is also some degree of variation within the species, with thermal limits increasing slightly during the summer.

## Daily values for the period examined by dataset
collection_conditions = temp_data %>%
  ungroup() %>% 
  group_by(date) %>% 
  summarise(mean_temp = mean(temp),
            med_temp = median(temp),
            var_temp = var(temp), 
            min_temp = min(temp), 
            max_temp = max(temp)) %>% 
  mutate("range_temp" = max_temp - min_temp,
         date = as.Date(date)) %>% 
  ungroup() %>%  
  filter(date >= (min(as.Date(full_data$collection_date)) - 7)) %>% 
  left_join(unique(select(full_data, collection_date, collection_temp)), by = join_by(date == collection_date))

## Mean female thermal limits for each species, grouped by collection
species_summaries = full_data %>%  
  #filter(sex == "female") %>% 
  group_by(sp_name, collection_date, collection_temp) %>%  
  summarise("mean_ctmax" = mean(ctmax),
            "sample_size" = n(),
            "ctmax_st_err" = (sd(ctmax) / sqrt(sample_size)),
            "ctmax_var" = var(ctmax), 
            "mean_size" = mean(size),
            "size_st_err" = (sd(size) / sqrt(sample_size)),
            "size_var" = var(size)) %>%  
  ungroup() %>% 
  complete(sp_name, collection_date) %>% 
  arrange(desc(sample_size))

adult_summaries = full_data %>%  
  filter(sex == "female") %>% 
  group_by(sp_name, collection_date, collection_temp) %>%  
  summarise("mean_ctmax" = mean(ctmax),
            "sample_size" = n(),
            "ctmax_st_err" = (sd(ctmax) / sqrt(sample_size)),
            "ctmax_var" = var(ctmax), 
            "mean_size" = mean(size),
            "size_st_err" = (sd(size) / sqrt(sample_size)),
            "size_var" = var(size)) %>%  
  ungroup() %>% 
  complete(sp_name, collection_date) %>% 
  arrange(desc(sample_size))


tseries_data = full_data %>% 
  mutate(sp_name = fct_reorder(sp_name, ctmax, .desc = T))

ggplot() + 
  geom_vline(data = unique(select(tseries_data, collection_date)), 
             aes(xintercept = as.Date(collection_date)),
             colour = "grey90",
             linewidth = 1) + 
  geom_line(data = collection_conditions, 
            aes(x = as.Date(date), y = mean_temp),
            colour = "black", 
            linewidth = 2) + 
  # geom_errorbar(data = species_summaries,
  #               aes(x = as.Date(collection_date),
  #                   ymin = mean_ctmax - ctmax_st_err, ymax = mean_ctmax + ctmax_st_err,
  #                   colour = sp_name),
  #               position = position_dodge(width = 1),
  #               width = 5, linewidth = 1) +
  # geom_point(data = adult_summaries, 
  #            aes(x = as.Date(collection_date), y = mean_ctmax, colour = sp_name, size = sample_size)) + 
  geom_point(data = tseries_data, 
             aes(x = as.Date(collection_date), y = ctmax, colour = sp_name),
             size = 2, position = position_jitter(width = 1, height = 0)) + 
  scale_colour_manual(values = species_cols) + 
  labs(x = "Date", 
       y = "Temperature (°C)", 
       colour = "Species",
       size = "Sample Size") + 
  theme_matt() + 
  theme(legend.position = "right")


lake_temps = ggplot() + 
  geom_line(data = collection_conditions, 
            aes(x = as.Date(date), y = mean_temp),
            colour = "black", 
            linewidth = 1) + 
  labs(x = "Date", 
       y = "Temperature (°C)", 
       colour = "Species",
       size = "Sample Size") + 
  theme_matt() + 
  theme(legend.position = "right")

Temperatures observed at the time of collection closely resembled the maximum daily temperature from the temperature sensor data. Maximum temperature was used as a proxy instead of mean temperature as collections were usually made during afternoons or early evenings, just following the warmest part of the day.

collection_conditions %>% 
  drop_na(collection_temp) %>%  
  ggplot(aes(x = max_temp, y = collection_temp)) + 
  geom_abline(intercept = 0, slope = 1,
              linewidth = 1, colour = "grey") + 
  geom_point(size = 3) +
  scale_x_continuous(breaks = c(5,15,25)) + 
  scale_y_continuous(breaks = c(5,15,25)) + 
  labs(x = "Max. Temp. from Sensor (°C)",
       y = "Collection Temp. (°C)") + 
  theme_matt()

Size also varied, but primarily between rather than within species.

ggplot() + 
  geom_vline(data = unique(select(full_data, collection_date)), 
             aes(xintercept = as.Date(collection_date)),
             colour = "grey90",
             linewidth = 1) + 
  geom_line(data = collection_conditions, 
            aes(x = as.Date(date), y = mean_temp),
            colour = "black", 
            linewidth = 2) + 
  # geom_errorbar(data = species_summaries,
  #               aes(x = as.Date(collection_date), 
  #                   ymin = mean_ctmax - ctmax_st_err, ymax = mean_ctmax + ctmax_st_err,
  #                   colour = sp_name),
  #               position = position_dodge(width = 1),
  #               width = 5, linewidth = 1) + 
  geom_point(data = adult_summaries, 
             aes(x = as.Date(collection_date), y = mean_size * 40, colour = sp_name, size = sample_size),
             position = position_dodge(width = 1)) + 
  scale_colour_manual(values = species_cols) + 
  scale_y_continuous(
    name = "Temperature", # Features of the first axis
    sec.axis = sec_axis(~./40, name="Prosome Length (mm)"), # Add a second axis and specify its features
    breaks = c(0,5,10,15,20,25,30)
  ) + 
  labs(x = "Date", 
       y = "Temperature (°C)", 
       colour = "Species") + 
  theme_matt() + 
  theme(legend.position = "right")

sample_dates_plot = full_data %>%  
  filter(sp_name != "Osphranticum labronectum") %>% 
  mutate(sp_name = as.factor(sp_name),
         sp_name = fct_reorder(sp_name, ctmax)) %>% 
  ggplot(aes(x = lubridate::as_date(collection_date), 
             y = sp_name, fill = sp_name)) + 
  # geom_vline(xintercept = as_date(
  #   c("2023-05-01",
  #     "2023-09-01",
  #     "2024-01-01",
  #     "2024-05-01")),
  #   colour = "grey",
  #   linewidth = 1) + 
  geom_density_ridges(bandwidth = 30,
                      jittered_points = TRUE, 
                      point_shape = 21,
                      point_size = 1,
                      point_colour = "grey30",
                      point_alpha = 0.8,
                      alpha = 0.8,
                      position = position_points_jitter(
                        height = 0.1, width = 0)) + 
  scale_fill_manual(values = species_cols) + 
  scale_x_date(date_breaks = "3 months",
               date_labels = "%b") + 
  coord_cartesian(xlim = lubridate::as_date(c("2023-06-08", "2024-05-08"))) + 
  labs(x = "Day of Year", 
       y = "Species") + 
  theme_matt() + 
  #theme_ridges(grid = T) + 
  theme(legend.position = "none",
        axis.text.x = element_text(angle = 270, hjust = 0, vjust = 0.5))

The samples captured the broad seasonal changes in calanoid copepod community composition in the lake. We note, however, that rare species (e.g. Senecella and Limnocalanus) were often preferentially sampled, so are over-represented in the data set.

Throughout the season, the prevalence of various unidentified pathogens also varied, with very little infection observed during the Winter and Spring.

pathogen_cols = c("no" = "grey95", "cloudy" = "honeydew3", "spot" = "antiquewhite3", "other" = "tomato3")

full_data %>% 
  select(collection_date, dev_eggs, pathogen, lipids, sp_name, sex) %>% 
  group_by() %>% 
  filter(sex != "juvenile") %>% 
  group_by(collection_date) %>% 
  count(pathogen) %>% 
  filter(pathogen != "uncertain") %>% 
  pivot_wider(id_cols = "collection_date", 
              names_from = pathogen, 
              values_from = n,
              values_fill = 0) %>% 
  mutate(total = sum(no, cloudy, spot, other)) %>% 
  pivot_longer(cols = c(no, cloudy, spot, other),
               names_to = "pathogen", 
               values_to = "count") %>% 
  mutate(percent = count/total,
         collection_date = lubridate::as_date(collection_date),
         pathogen = fct_relevel(pathogen, "no", "cloudy", "spot", "other")) %>% 
  ggplot(aes(x = collection_date, y = percent, fill = pathogen)) + 
  geom_area() + 
  scale_fill_manual(values = pathogen_cols) + 
  scale_y_continuous(breaks = c(0,1)) + 
  labs(x = "Collection Date", 
       y = "Proportion", 
       fill = "Pathogen") + 
  theme_minimal(base_size = 20) + 
  theme(panel.grid = element_blank(),
        axis.ticks = element_line())

The transparent bodies of these copepods also allowed us to examine seasonal patterns in lipid reserves and in the production of eggs. Maturing oocytes are visible in female copepods before they are released. There was no strong seasonal cycle in the production of these eggs in any species, and instead, females were reproductively active throughout their respective seasons of occurence.

dev_eggs_cols = c("no" = "grey95", "yes" = "lightblue3")

full_data %>% 
  select(collection_date, dev_eggs, pathogen, lipids, sp_name, sex) %>% 
  group_by(sp_name) %>% 
  filter(sex != "juvenile") %>% 
  group_by(sp_name, collection_date) %>% 
  count(dev_eggs) %>% 
  filter(dev_eggs != "uncertain") %>% 
  pivot_wider(id_cols = c("collection_date", "sp_name"), 
              names_from = dev_eggs, 
              values_from = n,
              values_fill = 0) %>% 
  mutate(total = sum(no, yes)) %>% 
  pivot_longer(cols = c(no, yes),
               names_to = "dev_eggs", 
               values_to = "count") %>% 
  mutate(percent = count/total,
         collection_date = lubridate::as_date(collection_date),
         dev_eggs = fct_relevel(dev_eggs, "no", "yes")) %>% 
  ungroup() %>% 
  complete(collection_date, nesting(sp_name, dev_eggs), fill = list(percent = 1)) %>% 
  mutate(percent = if_else(is.na(total) & dev_eggs == "yes", 0, percent)) %>% 
  ggplot(aes(x = collection_date, y = percent, fill = dev_eggs)) + 
  facet_wrap(sp_name~., ncol = 1) + 
  geom_area() + 
  scale_fill_manual(values = dev_eggs_cols) + 
  scale_y_continuous(breaks = c(0,1)) + 
  labs(x = "Collection Date", 
       y = "Proportion", 
       fill = "Developing \nEggs") + 
  theme_minimal(base_size = 20) + 
  theme(panel.grid = element_blank(),
        axis.ticks = element_line())

The presence of lipids varied across species, with only L. minutus, L. sicilis, and Limnocalanus regularly possessing lipid stores.

lipid_cols = c("no" = "grey95", "yes" = "sienna2")

full_data %>% 
  select(collection_date, dev_eggs, pathogen, lipids, sp_name, sex) %>% 
  group_by(sp_name) %>% 
  filter(sex != "juvenile") %>% 
  group_by(sp_name, collection_date) %>% 
  count(lipids) %>% 
  filter(lipids != "uncertain") %>% 
  pivot_wider(id_cols = c("collection_date", "sp_name"), 
              names_from = lipids, 
              values_from = n,
              values_fill = 0) %>% 
  mutate(total = sum(no, yes)) %>% 
  pivot_longer(cols = c(no, yes),
               names_to = "lipids", 
               values_to = "count") %>% 
  mutate(percent = count/total,
         collection_date = lubridate::as_date(collection_date),
         lipids = fct_relevel(lipids, "no", "yes")) %>% 
  ungroup() %>% 
  complete(collection_date, nesting(sp_name, lipids), fill = list(percent = 1)) %>% 
  mutate(percent = if_else(is.na(total) & lipids == "yes", 0, percent)) %>% 
  ggplot(aes(x = collection_date, y = percent, fill = lipids)) + 
  facet_wrap(sp_name~., ncol = 1) + 
  geom_area() + 
  scale_fill_manual(values = lipid_cols) + 
  scale_y_continuous(breaks = c(0,1)) + 
  labs(x = "Collection Date", 
       y = "Proportion", 
       fill = "Lipids\nPresent") + 
  theme_minimal(base_size = 20) + 
  theme(panel.grid = element_blank(),
        axis.ticks = element_line())

Temperature Variability

Lake Champlain is highly seasonal, with both average temperatures and temperature variability changing throughout the year. These patterns in the experienced thermal environment may drive the observed variation in copepod thermal limits. However, the time period affecting copepod thermal limits is unknown. Depending the on the duration of time considered, there are large changes in the experienced environment, in particular regarding the temperature range and variance. Consider for example three time periods: the day of collection, one week prior to collection, and four weeks prior to collection. While the overall pattern is similar, we can see that, unsurprisingly, considering longer periods of time results in larger ranges and slightly changes the pattern of variance experienced.

## Defining the function to get predictor values for periods of different lengths
get_predictors = function(daily_values, raw_temp, n_days){
  prefix = str_replace_all(xfun::numbers_to_words(n_days), pattern = " ", replacement = "-")
  
  mean_values = daily_values %>% 
    ungroup() %>% 
    mutate(mean_max = slide_vec(.x = max_temp, .f = mean, .before = n_days, .complete = T),
           mean_min = slide_vec(.x = min_temp, .f = mean, .before = n_days, .complete = T),
           mean_range = slide_vec(.x = range_temp, .f = mean, .before = n_days, .complete = T)) %>% 
    select(date, mean_max, mean_min, mean_range) %>% 
    rename_with( ~ paste(prefix, "day", .x, sep = "_"), .cols = c(-date))
  
  period_values = raw_temp %>% 
    mutate(mean = slide_index_mean(temp, i = date, before = days(n_days), 
                                   na_rm = T),
           max = slide_index_max(temp, i = date, before = days(n_days), 
                                 na_rm = T),
           min = slide_index_min(temp, i = date, before = days(n_days),
                                 na_rm = T),
           med = slide_index_dbl(temp, .i = date, .before = days(n_days), 
                                 na_rm = T, .f = median),
           var = slide_index_dbl(temp, .i = date, .before = days(n_days), 
                                 .f = var),
           range = max - min) %>%  
    select(-temp) %>%  
    distinct() %>% 
    rename_with( ~ paste(prefix, "day", .x, sep = "_"), .cols = c(-date))%>% 
    inner_join(mean_values, by = c("date")) %>%  
    drop_na()
  
  return(period_values)
}

Organisms are unlikely to acclimate instantaneously to changes in temperature. To explore the potential temporal window these copepods are responding to, we examined the correlation between thermal limits and summaries of the thermal environment over different periods of time. For each species (inclusive of all sexes and stages), we examined the correlation between CTmax and one of nine representations of the thermal environment calculated for periods of time from 1 to 60 days before collection. These parameters include the overall maximum, minimum, median, and mean temperature for the period of time, the temperature range and variance during this time, and the mean daily temperature maximum, minimum, and range. We also examined the correlation between CTmax and the temperature recorded at the time of collection.

Shown below are the correlation coefficients for these relationships. Each facet shows the relationship for a different parameter, plotted against the duration of the time period before collection.

corr_vals %>% 
  mutate(parameter = fct_relevel(parameter, c("min", "max", "range",
                                              "mean", "med", "var",
                                              "mean_min", "mean_max", "mean_range"))) %>% 
  ggplot(aes(x = duration, y = correlation, colour = sp_name)) + 
  facet_wrap(.~parameter) + 
  geom_hline(yintercept = 0) + 
  geom_point(size = 0.9) + 
  geom_line(linewidth = 1.5) + 
  scale_colour_manual(values = species_cols) + 
  labs(x = "Duration (days)",
       y = "Correlation", 
       colour = "Species") + 
  theme_matt_facets()

This table contains the top three factors for each species (based on correlation coefficient).

Shown here is a graphical summary of the duration of the best predictors for each species. Note that for the two Leptodiaptomids, collection temperature had the largest correlation coefficient so duration is zero. This representation highlights that there is variation across the community not only in the potential driver (e.g. minimum vs. maximum temperatures) but also in the duration of time. This variation is not grouped by season (the winter and summer communities both have representative species apparently responding to short and long durations).

duration_plot = corr_vals %>%  
  filter(sig == "Sig.") %>% 
  drop_na(correlation) %>% 
  group_by(sp_name) %>%
  arrange(desc(correlation)) %>% 
  slice_head(n = 1) %>% 
  ungroup() %>% 
  mutate("num" = row_number(), 
         sp_name = fct_reorder(sp_name, duration, .fun = mean, .desc = T)) %>% 
  arrange(sp_name) %>% 
  select("Species" = sp_name, "Predictor" = parameter, "Duration" = duration, "Correlation" = correlation, num) %>% 
  ggplot(aes(x = Species, y = Duration, fill = Predictor, group = num)) + 
  geom_bar(stat = "identity", width = 0.5, position = position_dodge(width = 0.6),
           colour = "black") + 
  scale_fill_manual(values = c("coll_temp" = "black", "max" = "white", "min" = "grey")) + 
  labs(x = "", 
       y = "Duration \n(days)") + 
  theme_matt() + 
  theme(axis.text.x = element_blank())
correlation_coef_plot = corr_vals %>%  
  filter(sig == "Sig." | parameter == "coll_temp") %>% 
  drop_na(correlation) %>% 
  group_by(sp_name) %>%
  filter(parameter == "coll_temp" | correlation == max(correlation)) %>% 
  arrange(sp_name, parameter) %>% 
  mutate("num" = row_number()) %>% 
  select("Species" = sp_name, "Predictor" = parameter, "Duration" = duration, "Correlation" = correlation, num) %>% 
  mutate(Predictor = if_else(Predictor == "coll_temp", Predictor, "best")) %>% 
  ungroup() %>% 
  mutate(Species = fct_reorder(Species, Duration, .fun = max, .desc = T)) %>% 
  ggplot(aes(x = Species, y = Correlation, fill = Predictor, group = num)) + 
  geom_bar(stat = "identity", width = 0.5, position = position_dodge(width = 0.6),
           colour = "black") + 
  labs(y = "Correlation \nCoefficient",
       fill = "Correlate") +
  scale_fill_manual(values = c("coll_temp" = "black", "best" = "white")) + 
  scale_y_continuous(breaks = c(0, 1), limits = c(0,1)) +
  theme_matt() + 
  theme(axis.text.x = element_text(angle = 300, hjust = 0, vjust = 0.5))

ggarrange(duration_plot, correlation_coef_plot, nrow = 2, legend = "right", 
          heights = c(0.4, 0.6))

Trait Variation

Shown below are the clutch size distributions for the three diaptomiid species, which produce egg sacs that allow for easy quantification of fecundity.

full_data %>%  
  drop_na(fecundity) %>%  
  ggplot(aes(x = fecundity, fill = sp_name_sub)) + 
  facet_wrap(.~sp_name_sub, ncol = 1) + 
  geom_histogram(binwidth = 2) + 
  scale_fill_manual(values = species_cols) + 
  labs(x = "Fecundity (# Eggs)") +
  theme_matt_facets() + 
  theme(legend.position = "none")

One of the main aims of this project is to examine the patterns and processes driving variation in upper thermal limits across these species of copepods.

Variation with temperature

We expect one of the primary drivers of copepod thermal limits to be temperature, as individuals acclimate to seasonal changes. Shown below are the seasonal patterns of when copepods were included in CTmax measurements (a proxy for the season of occurrence), and thermal limits for each species plotted against the temperature at the time of collection. We generally see an increase in thermal limits with increasing collection temperature.

sp_ctmax_temp = full_data %>% 
  filter(sp_name != "Osphranticum labronectum") %>% 
  mutate(sp_name = as.factor(sp_name),
         sp_name = fct_reorder(sp_name, ctmax, .desc = T)) %>% 
  ggplot(aes(x = collection_temp, y = ctmax, colour = sp_name)) + 
  facet_wrap(sp_name~.) + 
  geom_smooth(method = "lm", se = F, linewidth = 1.5, colour = "grey30") + 
  geom_point(size = 2, alpha = 0.4) + 
  labs(x = "Collection Temp. (°C)", 
       y = "CTmax (°C)") + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "none")
ggarrange(sample_dates_plot, sp_ctmax_temp, nrow = 1, 
          labels = "AUTO")

The interaction between seasonal changes in temperature and the acclimation of thermal limits likely affects vulnerability of each species to warming. Shown below are warming tolerance values for each species, calculated as the difference between individual CTmax and the temperature at the time of collection. All species maintained some degree of buffer between environmental temperatures and upper thermal limits, but L. minutus appears to approach its upper thermal limit during the warmest collections during the summer.

Also shown below is the relationship between fecundity (the number of eggs contained in a clutch) for the three diaptomid species. For the two Leptodiaptomus species, there is no relationship between clutch size and temperature, while there appears to be a general increase in clutch size with temperature in the Skistodiaptomus species.


wt_temp = full_data %>% 
  filter(sp_name != "Osphranticum labronectum") %>% 
  ggplot(aes(x = collection_temp, y = warming_tol, colour = sp_name)) + 
  geom_point(size = 3,
             alpha = 0.3) + 
  geom_smooth(method = "lm", linewidth = 3) +
  labs(x = "Collection Temperature (°C)", 
       y = "Warming Tolerance (°C)",
       colour = "Species")  + 
  ylim(0,30) + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "none")

eggs_temp = full_data %>% 
  filter(sp_name != "Osphranticum labronectum") %>% 
  ggplot(aes(x = collection_temp, y = fecundity, colour = sp_name)) + 
  geom_point(size = 3,
             alpha = 0.3) + 
  geom_smooth(method = "lm", linewidth = 3) +
  labs(x = "Collection Temperature (°C)", 
       y = "Fecundity (# Eggs)",
       colour = "Species")  + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "right")

ggarrange(wt_temp, eggs_temp, 
          common.legend = T, legend = "right")

# Copepods spent several days in lab during experiments. Shown below are the CTmax residuals (taken from a model of CTmax against collection temperature) plotted against the time spent in lab before measurements were made. Individual regressions are shown for the residuals against days in lab for each collection. We can see clearly that thermal limits are fairly stable over time. 


# ggplot(ctmax_resids, aes(x = days_in_lab, y = resids, colour = sp_name, group = collection_date)) + 
#   facet_wrap(sp_name~.) + 
#   geom_point(size = 4, alpha = 0.5) + 
#   geom_smooth(method = "lm", se = F, linewidth = 1) + 
#   #scale_x_continuous(breaks = c(0:5)) + 
#   labs(x = "Days in lab", 
#        y = "CTmax Residuals") + 
#   scale_colour_manual(values = species_cols) + 
#   theme_matt_facets() + 
#   theme(legend.position = "none")

model_data = full_data %>%  
  drop_na(size, ctmax) %>%  
  filter(sp_name != "Osphranticum labronectum") %>% 
  mutate(temp_cent = scale(collection_temp, center = T, scale = F),
         size_cent = scale(size, center = T, scale = F))

minimal.model = lme4::lmer(data = model_data,
                           ctmax ~ sp_name + sex + temp_cent +
                             (1|days_in_lab))

full.model = lme4::lmer(data = filter(model_data, sp_name != "Osphranticum labronectum"),
                        ctmax ~ sp_name*sex*temp_cent +
                          (1|days_in_lab))

drop1(full.model, test = "Chisq")
## Single term deletions
## 
## Model:
## ctmax ~ sp_name * sex * temp_cent + (1 | days_in_lab)
##                       npar    AIC    LRT Pr(Chi)  
## <none>                     5280.1                 
## sp_name:sex:temp_cent   10 5281.0 20.887  0.0219 *
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

performance::test_performance(minimal.model, full.model)
## Name          |   Model |    BF | df | df_diff |   Chi2 |      p
## ----------------------------------------------------------------
## minimal.model | lmerMod |       | 11 |         |        |       
## full.model    | lmerMod | 0.001 | 38 |   27.00 | 180.70 | < .001
## Models were detected as nested (in terms of fixed parameters) and are compared in sequential order.
performance::check_model(full.model)


car::Anova(full.model, type = "III")
## Analysis of Deviance Table (Type III Wald chisquare tests)
## 
## Response: ctmax
##                          Chisq Df Pr(>Chisq)    
## (Intercept)           4619.014  1  < 2.2e-16 ***
## sp_name                344.724  5  < 2.2e-16 ***
## sex                     51.233  2  7.495e-12 ***
## temp_cent               53.731  1  2.299e-13 ***
## sp_name:sex             10.611 10    0.38866    
## sp_name:temp_cent       39.512  5  1.873e-07 ***
## sex:temp_cent           31.961  2  1.147e-07 ***
## sp_name:sex:temp_cent   20.616 10    0.02393 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

sp_ctmax = emmeans::emmeans(full.model, specs = "sp_name") %>% 
  data.frame() %>% 
  select(sp_name, "species_ctmax" = emmean)

model_coefs = emmeans::emtrends(full.model, var = "temp_cent", specs = "sp_name") %>% 
  data.frame() %>% 
  inner_join(sp_ctmax) 

ctmax_resids = model_data %>% 
  mutate(resids = residuals(full.model))
arr_combined = synth_arr %>%
  filter(measure == "upper" & mean_lim > 20) %>% 
  select("group" = genus, arr, mean_lim) %>% 
  mutate("dataset" = "synthesis") %>% 
  bind_rows(
    select(model_coefs, "group" = sp_name, 'arr' = temp_cent.trend, 'mean_lim' = species_ctmax)
  ) %>% 
  mutate(dataset = if_else(is.na(dataset), "new data", "synthesis"),
         group = fct_reorder(group, arr, .desc = T))


ggplot(arr_combined, aes(x = mean_lim, y = arr)) + 
  geom_smooth(method = "lm", se = F, 
              linewidth = 2, colour = "grey30") + 
  geom_point(data = filter(arr_combined, dataset != "new data"), 
             size = 4, colour = "grey") + 
  geom_point(data = filter(arr_combined, dataset == "new data"),
             aes(colour = group), 
             size = 4) + 
  scale_colour_manual(values = species_cols) + 
  labs(x = "Thermal Limit", 
       y = "ARR", 
       colour = "Species") +
  theme_matt() + 
  theme(legend.position = "right")

Sex and stage variation in thermal limits

Previous sections have generally lumped juvenile, female, and male individuals together. There may be important stage- or sex-specific differences in CTmax though. For all species but Osphranticum, we have measurements for individuals in different stages and of different sexes.

sex_sample_sizes = full_data %>%  
  group_by(sp_name, sex) %>%  
  summarise(num = n()) %>%  
  pivot_wider(id_cols = sp_name,
              names_from = sex, 
              values_from = num,
              values_fill = 0) %>% 
  select("Species" = sp_name, "Juvenile" = juvenile, "Female" = female, "Male" = male)

knitr::kable(sex_sample_sizes, align = "c")
Species Juvenile Female Male
Epischura lacustris 37 45 20
Leptodiaptomus minutus 12 273 39
Leptodiaptomus sicilis 31 356 95
Limnocalanus macrurus 4 43 39
Osphranticum labronectum 0 1 0
Senecella calanoides 13 21 8
Skistodiaptomus sp 15 232 28

Across group comparisons show that there are generally no differences in thermal limits (represented here as the residuals from a CTmax ~ collection_temp x species linear regression), with the exception of Senecella males, which may have lower thermal limits (although sample sizes are very small in this group).

# ctmax_resids %>% 
#   filter(sp_name != "Osphranticum labronectum") %>% 
#   ggplot(aes(x = sex, y = resids, colour = sp_name)) + 
#   facet_wrap(sp_name~.) + 
#   geom_jitter(width = 0.1, alpha = 0.5) + 
#   geom_boxplot(width = 0.4, fill = NA, colour = "black", 
#                linewidth = 1, outlier.colour = NA) + 
#   scale_colour_manual(values = species_cols) + 
#   theme_matt_facets()
model2_data = model_data %>% 
  filter(sex == "female", 
         pathogen != "uncertain", 
         dev_eggs != "uncertain", 
         lipids != "uncertain") %>% 
  mutate(pathogens = fct_relevel(pathogen, "no", "spot", "cloudy", "other"))

other_factor_model = lmer(data = model2_data, 
                          ctmax~sp_name * collection_temp + dev_eggs + pathogen + lipids + (1|days_in_lab))

drop1(other_factor_model, scope = ~., test = "Chisq")
## Single term deletions
## 
## Model:
## ctmax ~ sp_name * collection_temp + dev_eggs + pathogen + lipids + 
##     (1 | days_in_lab)
##                         npar    AIC     LRT   Pr(Chi)    
## <none>                       3601.6                      
## sp_name                    5 3804.2 212.619 < 2.2e-16 ***
## collection_temp            0 3601.6   0.000              
## dev_eggs                   1 3602.0   2.391    0.1220    
## pathogen                   3 3629.4  33.832 2.149e-07 ***
## lipids                     1 3600.0   0.416    0.5189    
## sp_name:collection_temp    5 3635.7  44.139 2.171e-08 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

reduced_factors_model = lmer(data = model2_data, 
                          ctmax~sp_name * collection_temp + pathogen + (1|days_in_lab))

performance::check_model(reduced_factors_model)

emmeans::emmeans(reduced_factors_model, spec = "pathogen") %>% emmeans::contrast(method="trt.vs.ctrl",ref="no") %>% plot() + 
  geom_vline(xintercept = 0) + 
  labs(x = "Difference (°C)", 
       y = "Comparison") + 
    theme_matt()

Trait Correlations and Trade-offs

A relationship between size and upper thermal limits has been suggested in a wide range of other taxa. Shown below are the measured upper thermal limits plotted against prosome length. The overall relationship (inclusive of all species) is shown as the black line in the background. Regressions for each individual species are also shown. Across the entire assemblage, there is a strong decrease in thermal limits with increasing size.

full_data %>% 
  #filter(sex == "female") %>%  
  ggplot( aes(x = size, y = ctmax, colour = sp_name)) + 
  geom_point(size = 2, alpha = 0.3) + 
  geom_smooth(data = full_data, 
              aes(x = size, y = ctmax),
              method = "lm", 
              colour ="black", 
              linewidth = 2.5) + 
  labs(x = "Length (mm)", 
       y = "CTmax (°C)",
       colour = "Species") + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "right")

Shown here is the relationship for each species individually.

full_data %>% 
  #filter(sex == "female") %>%  
  group_by(sp_name) %>% filter(n() >2) %>% filter(!str_detect(sp_name, pattern = "kindti")) %>% 
  ggplot( aes(x = size, y = ctmax, colour = sp_name)) + 
  facet_wrap(sp_name~., scales = "free", nrow = 2) + 
  geom_point(size = 2, alpha = 0.8) + 
  geom_smooth(method = "lm", se = F, linewidth = 2) + 
  labs(x = "Length (mm)", 
       y = "CTmax (°C)",
       colour = "Species") + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "none")

Shown below is the relationship between mean size and mean thermal limits for females of each species. We see that larger species within the community tend to have a lower thermal limit than smaller species.

full_data %>% 
  group_by(sp_name, sex) %>% 
  summarize(mean_ctmax = mean(ctmax, na.rm = T),
            mean_size = mean(size, na.rm = T)) %>% 
  #filter(sex == "female") %>% 
  ggplot(aes(x = mean_size, y = mean_ctmax)) + 
  geom_smooth(method = "lm", se = F, linewidth = 2, colour = "black") + 
  geom_point(aes(colour = sp_name, shape = sex),
             size = 5) + 
  labs(x = "Length (mm)", 
       y = "CTmax (°C)",
       colour = "Species") + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "right")

Shown here is the relationship between fecundity and size, showing the classic pattern of increasing egg production with increasing size.

size_fecund_plot = ctmax_resids %>%  
  drop_na(fecundity) %>% 
  ggplot(aes(x = size, y = fecundity, colour = sp_name)) + 
  geom_smooth(method = "lm", se = F, linewidth = 2) + 
  geom_point(size = 2, alpha = 0.5) + 
  labs(x = "Prosome length (mm)", 
       y = "Fecundity (# Eggs)",
       colour = "Species") + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "right")

Individuals may also allocate energy to different fitness related traits, prioritizing reproductive output over environmental tolerance, for example. Shown below is the relationship between CTmax residuals (again, controlling for the effects of collection temperature) against fecundity. We can see clearly that individuals with increased fecundity are not decreasing thermal limits, suggesting that there is no energetic trade-off between these traits.

ctmax_fecund_plot = ctmax_resids %>%  
  drop_na(fecundity) %>% 
  ggplot(aes(x = resids, y = fecundity, colour = sp_name)) + 
  geom_smooth(method = "lm", se = F, linewidth = 2) + 
  geom_point(size = 2, alpha = 0.5) + 
  labs(x = "CTmax Residuals (°C)", 
       y = "Fecundity (# Eggs)",
       colour = "Species") + 
  scale_colour_manual(values = species_cols) + 
  theme_matt() + 
  theme(legend.position = "right")

ggarrange(size_fecund_plot, ctmax_fecund_plot, ncol = 1, common.legend = T, legend = "right")

Previous studies have shown that the magnitude of the size-fecundity correlation may be environmentally-dependent. This is not visible is the data from these collections.

corr_data = full_data %>% 
  drop_na(fecundity) %>% 
  filter(sp_name %in% c("Leptodiaptomus sicilis",
                        "Leptodiaptomus minutus", 
                        "Skistodiaptomus sp")) %>%  
  group_by(collection_date, collection_temp, sp_name) %>% 
  summarise(size_fec_corr = cor(size, fecundity),
            n = n(),
            mean_fecundity = mean(fecundity)) %>% 
  filter(n >= 3) %>% 
  ungroup() %>%  
  group_by(sp_name) %>% 
  mutate(temp_cent = scale(collection_temp, scale = F))

ggplot(corr_data, aes(x = temp_cent, y = size_fec_corr, colour = sp_name)) + 
  facet_wrap(sp_name~., nrow = 3) + 
  geom_hline(yintercept = 0) +
  geom_point(size = 3) + 
  geom_smooth(method = "lm", linewidth = 2) + 
  scale_color_manual(values = species_cols) + 
  labs(x = "Temperature (centered)", 
       y = "Correlation Coefficient") + 
  coord_cartesian(ylim = c(-1, 1)) +
  theme_matt_facets() + 
  theme(legend.position = "none")


# ggplot(corr_data, aes(x = size_fec_corr)) +
#     facet_wrap(sp_name~., nrow = 3) +
#   geom_histogram(binwidth = 0.2)

Other patterns in variation

Leptodiaptomus sicilis is the most abundant species during the winter. There was a large shift in the size of mature females towards the end of December. These large and small individuals are the same species (confirmed via COI sequencing), suggesting this shift may instead reflect a transition from one generation to another. This size difference may be caused by differences in the developmental environments. For example, individuals developing in January grow up at very low temperatures, and therefore may reach larger sizes. These individuals over-summer in deep waters, then re-emerge in October and produce a new generation. Water temperatures are still fairly high through November, which results in a generation of smaller individuals. These individuals mature in time to produce a new generation in January.

full_data %>%  
  filter(sp_name == "Leptodiaptomus sicilis") %>% 
  filter(sex != "juvenile") %>% 
  group_by(collection_date) %>% 
  mutate(size_center = scale(size, center = T, scale = F)) %>% 
  ggplot(aes(y = factor(collection_date), x = size, fill = collection_temp)) + 
  facet_wrap(sex~.) + 
  geom_density_ridges(bandwidth = 0.04) + 
  geom_vline(xintercept = 0.89) + 
  labs(x = "Size (mm)",
       y = "Date", 
       fill = "Coll. Temp. (°C)") + 
  theme_matt() + 
  theme(legend.position = "right",
        axis.text.y = element_text(size = 12))

A similar, but less distinct pattern can be observed in L. minutus individuals as well.

full_data %>%  
  filter(sp_name == "Leptodiaptomus minutus") %>% 
  filter(sex != "juvenile") %>% 
  ggplot(aes(y = factor(collection_date), x = size, fill = collection_temp)) + 
  facet_wrap(sex~.) + 
  geom_density_ridges(bandwidth = 0.04) + 
  geom_vline(xintercept = 0.69) + 
  labs(x = "Size (mm)",
       y = "Date", 
       fill = "Coll. Temp. (°C)") + 
  coord_cartesian(xlim = c(0.5,0.9)) + 
  theme_matt() + 
  theme(legend.position = "right",
        axis.text.y = element_text(size = 12))

Distribution Lag Non-Linear Model (DLNM approach)

Distributed lag models examine a response variable, measured at multiple time points, as a function of the lagged occurrence of some predictor variable (response y at time t as a function of predictor x(t-lag). This method utilizes a bi-dimensional dose-lag-response function, which essentially examines not only the dose effect, but the effect of the timing of the dose.

# Run this code, save the product, and then just read in the temp lag data object. Takes too long to run each time this document is knit. 

# lag_temps = temp_data %>%
#   group_by(date, hour) %>%
#   summarize("mean_temp" = mean(temp, na.rm = T)) %>%
#   ungroup() %>%
#   mutate(point_num = row_number())
# 
# uniq_days = length(unique(lag_temps$date))
# 
# g = gam(mean_temp ~ s(point_num, bs="cr", k=uniq_days + 10),
#     method = "REML",
#     data = lag_temps)
# 
# points = seq(1, nrow(lag_temps), length.out = length(lag_temps$hour))
# 
# df.res = df.residual(g)
# 
# pred_temps = predict(g, newdata = lag_temps, type = "response", se.fit = TRUE)
# 
# lag_temps = lag_temps %>%
#   mutate(trend_T = pred_temps$fit,
#          trend_se = pred_temps$se.fit,
#          temp_diff = mean_temp - trend_T)
# 
# write.csv(lag_temps, file = "./Output/Data/lag_temps.csv", row.names = F)

dlnm_data = full_data %>%  
  filter(sex == "female") %>% 
  filter(sp_name %in% c(
    "Leptodiaptomus sicilis",
    "Leptodiaptomus minutus",
    "Skistodiaptomus sp"
  )) %>% 
  select(collection_date, collection_temp, sp_name, ctmax) %>% 
  group_by(collection_date, collection_temp, sp_name) %>%  
  summarise(mean_ctmax = mean(ctmax, na.rm = T),
            sample = n())

temp_data %>% 
  group_by(date) %>% 
  summarise(mean_temp = mean(temp),
            max_temp = max(temp, na.rm = T)) %>% 
  right_join(dlnm_data, by = join_by("date" == "collection_date")) %>% 
  ggplot(aes(x = max_temp, y = mean_ctmax)) + 
  facet_wrap(.~sp_name) + 
  geom_smooth(method = "gam") + 
  geom_point() + 
  labs(x = "Max Daily Temp. (°C)",
       y = "Mean CTmax (°C)") + 
  theme_matt_facets() + 
  theme(strip.text.x = element_text(size = 12))


sp_list = unique(dlnm_data$sp_name)

for(lag_species in sp_list){
  
  dlnm_data_sp = dlnm_data %>% 
    filter(sp_name == lag_species)
  
  # We need to estimate a matrix of exposure histories for each observation. This contains the series of exposures at each lag (l) for each of the n observations, constrained between l0 (minimum lag) and L (max lag). 
  
  dates = dlnm_data_sp$collection_date # For each of these dates, make a vector of the past 30 days (including the day of collection). NOTE: Don't use 'unique' dates here since some collections had multiple species
  
  exp_hist_z = data.frame()
  exp_hist_trend = data.frame()
  
  for(d in dates){
    
    history = lag_temps %>% 
      filter(date <= d & date > d - 10) %>% 
      arrange(desc(date), desc(hour)) %>% 
      mutate(lag = row_number() - 1) %>% 
      select(lag, mean_temp, temp_diff)
    
    z_vec = scale(history$mean_temp)[,1]
    names(z_vec) = history$lag
    
    trend_vec = history$temp_diff
    names(trend_vec) = history$lag
    
    exp_hist_z = bind_rows(exp_hist_z, z_vec)
    exp_hist_trend = bind_rows(exp_hist_trend, trend_vec)
    
  }
  
  #print(max(exp_hist_trend, na.rm = T))
  
  # The cross-basis function from dlnm will use the class of the x parameter to determine what to do. In our case, we need to provide it with the matrix of exposure histories for reach observation (row) and lag (column). 
  
  cb_temps = crossbasis(exp_hist_trend, lag = c(0,dim(exp_hist_trend)[2]-1), 
                        argvar =list(fun="cr",df=3), 
                        arglag=list(fun="cr",df=3,intercept=T))
  
  #summary(cb_temps)
  
  penalized_mat <- cbPen(cb_temps)
  
  #fitting GAM
  lag.gam = gam(data = dlnm_data_sp, 
                mean_ctmax ~ collection_temp + cb_temps, 
                method = "GCV.Cp",
                paraPen=list(cb_temps=penalized_mat))
  
  # summary(lag.gam)
  # AIC(lag.gam)
  
  #estimation of exposures effects
  
  #default plots
  pred_gam_Zs<-crosspred(cb_temps, lag.gam, 
                         cumul=F, cen=0, ci.level = 0.95,
                         at=seq(-4,4, 0.1))
  
  plot(pred_gam_Zs, "contour", main = lag_species)
  # 
  # plot(pred_gam_Zs, border = 2, cumul=F,
  #       theta=110,phi=20,ltheta=-80)
  
  plot(pred_gam_Zs, "slices",
       var = c(3,-3),
       lag = c(1,200),
       col = 2)
  
}

Hindcasting vulnerability with different acclimation scenarios

Using the observed thermal limit data, we can produce a hindcast of thermal stress for Lake Champlain copepods. For these initial assays, we will define thermal stress as any time when maximum daily water temperature is within 5°C of copepod CTmax or higher (i.e. warming tolerance is less than 5°C). We will use three different scenarios: 1) each species has a unique but fixed thermal limit (average measured CTmax), 2) species have unique thermal limits and are able to acclimate (constant ARR across all species used to predict CTmax based on average daily temperatures), and 3) species have unique thermal limits and species-specific acclimation (CTmax predicted using whichever environmental factor and duration is the strongest candidate for driving acclimation - from the correlation analysis). In all cases, data is filtered to just thermal limits of adult females.

Scenario 1

mean_ctmax = full_data %>% 
  filter(sex == "female") %>%  
  group_by(sp_name) %>% 
  summarize("mean_ctmax" = mean(ctmax)) %>% 
  arrange(mean_ctmax)

knitr::kable(mean_ctmax)
sp_name mean_ctmax
Senecella calanoides 22.04400
Limnocalanus macrurus 22.88927
Leptodiaptomus sicilis 29.15785
Leptodiaptomus minutus 31.53916
Epischura lacustris 31.85441
Skistodiaptomus sp 35.67407
Osphranticum labronectum 36.31250
# # Constructs the URL for the full temperature data set; RUN THIS ONCE
# hind_url = constructNWISURL(siteNumbers = siteNumber, parameterCd = parameterCd, service = "uv")
# 
# hind_temp_data = importWaterML1(hind_url, asDateTime = T) %>%
#   mutate("date" = as.Date(dateTime)) %>%
#   select(date, "temp" = X_00010_00000)
# 
# write.table(x = hind_temp_data, file = "hindcast_temps.csv", row.names = F, sep = ",")
# ggplot(hind_temp_data, aes(x = date, y = temp)) + 
#   geom_line(linewidth = 0.1) + 
#   labs(x = "Date", 
#        y = "Water Temperature (°C)") +
#   theme_matt()

In the simplest scenario, species thermal limits are static through time, represented by the average CTmax of adult female copepods. In this scenario, only three of the seven observed species are exposed to thermal stress (temperatures within 5°C of CTmax). Temperatures approached the thermal limit of Leptodiaptomus sicilis on a handful of days. By contrast, Senecella calanoides and Limnocalanus macrurus were both exposed to substantial thermal stress throughout a large portion of the year, likely explaining why these species are absent from the community for the summer and fall periods.

hind1_data = hind_temp_data %>% 
  group_by(date) %>% 
  summarize("daily_max" = max(temp),
            "daily_mean" = mean(temp),) %>% 
  bind_cols(pivot_wider(mean_ctmax, names_from = sp_name, values_from = mean_ctmax)) %>%  
  pivot_longer(cols = c(-date, -daily_max, -daily_mean),
               names_to = "species", 
               values_to = "mean_ctmax") %>%  
  mutate(lim_diff = mean_ctmax - daily_max) %>%  
  mutate(doy = yday(date),
         "method" = "No_acclimation")

hind_daily_temp_data = hind_temp_data %>%
  ungroup() %>% 
  group_by(date) %>% 
  summarise(mean_temp = mean(temp),
            med_temp = median(temp),
            var_temp = var(temp), 
            min_temp = min(temp), 
            max_temp = max(temp)) %>% 
  mutate("range_temp" = max_temp - min_temp)

#table(hind1_data$species)

hind1_data %>% 
  filter(lim_diff <= 5) %>%  
  ggplot(aes(x = doy, y = lim_diff, colour = species)) +
  geom_hline(yintercept = 0) + 
  geom_hline(yintercept = 5, 
             colour = "grey") + 
  geom_point(alpha = 0.5) +
  geom_smooth(se = F) + 
  labs(x = "Day of Year", 
       y = "Predicted Warming Tolerance \n(°C Above Daily Max)") + 
  theme_matt() + 
  theme(legend.position = "right")

Scenario 2

In the second scenario, thermal limits vary within and between species. A simple model is used to predict species thermal limits based on mean daily temperature (CTmax as a function of species and collection temperature, but without the interaction between these two factors). These predicted thermal limits are then compared against the maximum daily temperature to estimate thermal stress, as in Scenario 1. Including this simple form of acclimation in the model reduced the degree of thermal stress for each species, eliminating it entirely for Leptodiaptomus sicilis. Note that the magnitude of the predicted stress is low enough that removing the 5°C buffer around the predicted thermal limits would actually limit predicted thermal stress to just a few days for Senecella calanoides.

hindcast_model1 = lm(data = filter(full_data, sex == "female"),
                     ctmax ~ collection_temp + sp_name)

hind2_data = hind_temp_data %>% 
  group_by(date) %>% 
  summarize("collection_temp" = mean(temp),
            "daily_max" = max(temp)) %>% 
  bind_cols(
    pivot_wider(mean_ctmax, 
                names_from = sp_name, 
                values_from = mean_ctmax)) %>% 
  pivot_longer(cols = c(-date, -daily_max, -collection_temp),
               names_to = "sp_name", 
               values_to = "mean_ctmax") %>% 
  select(-mean_ctmax) %>% 
  mutate("pred_ctmax" = predict.lm (hindcast_model1, newdata = .)) %>% 
  select(date, "daily_mean" = collection_temp, daily_max, "species" = sp_name, pred_ctmax) %>% 
  mutate(lim_diff = pred_ctmax - daily_max) %>% 
  #filter(lim_diff <= 0) %>%  
  mutate(doy = yday(date),
         "method" = "Constant_acclimation")

# ggplot(hind2_data, aes(x = daily_mean, y = pred_ctmax, colour = species)) +
#   geom_smooth(method = "lm") 

# table(hind2_data$species)
hind2_data %>%  
  filter(lim_diff <= 5) %>%  
  ggplot(aes(x = doy, y = lim_diff, colour = species)) +
  geom_hline(yintercept = 0) + 
  geom_hline(yintercept = 5, 
             colour = "grey") + 
  geom_point(alpha = 0.5) +
  geom_smooth() + 
  labs(x = "Day of Year", 
       y = "Predicted Warming Tolerance \n(°C Above Daily Max)") + 
  theme_matt() + 
  theme(legend.position = "right")

Scenario 3

The final scenario allows the environmental variable used to predict CTmax to vary between species. For species observed in fewer than 5 collections, we use the same approach as in Scenario 2. For species observed in more than 5 collections, however, the factor with the strongest correlation with CTmax is used to predict thermal limits. These factors are included below.

hind_preds = corr_vals %>%  
  filter(sig == "Sig.") %>% 
  drop_na(correlation) %>% 
  group_by(sp_name) %>%
  arrange(desc(correlation)) %>% 
  slice_head(n = 1) %>% 
  select("Species" = sp_name, "Predictor" = parameter, "Duration" = duration, "Correlation" = correlation, "P-Value" = p.value)

knitr::kable(hind_preds, align = "c")
Species Predictor Duration Correlation P-Value
Epischura lacustris max 29 0.9147764 0.0000000
Leptodiaptomus minutus coll_temp 0 0.7732711 0.0000000
Leptodiaptomus sicilis coll_temp 0 0.2833554 0.0000001
Limnocalanus macrurus min 8 0.5496742 0.0000000
Senecella calanoides max 19 0.5038896 0.0006688
Skistodiaptomus sp max 2 0.7972819 0.0000000
hind3_data = hind2_data %>% # Contains data for species that won't change from scenario 2
  filter(!(species %in% corr_vals$sp_name))

preds_to_pull = hind_preds %>%  
  select(Species, Predictor, Duration) 

for(i in 1:length(preds_to_pull$Species)){
  
  duration = preds_to_pull$Duration[i]
  
  if(duration == 0){ #The prior day temperature metrics should be used
    
    predictors = hind_daily_temp_data %>% 
      mutate(date = date) 
    
    parameter = "mean_temp" #using mean temperature as a proxy for collection temp
    
    model_data = full_data %>%
      filter(sp_name %in% preds_to_pull$Species[i]) %>% 
      filter(sex == "female") %>% 
      mutate(collection_date = as_date(collection_date)) %>% 
      inner_join(predictors, join_by(collection_date == date)) %>%  
      select(ctmax, contains(parameter))
    
    if(dim(model_data)[2] == 2){
      hind.model = lm(data = model_data, 
                      ctmax ~ .)
      
      sp_data = predictors %>% 
        select(date, contains(parameter)) %>% 
        mutate(pred_ctmax = predict(hind.model, newdata = .)) %>%  
        select(date, pred_ctmax) %>% 
        inner_join(hind_daily_temp_data, by = c("date")) %>% 
        mutate("species" = preds_to_pull$Species[i],
               "doy" = yday(date),
               lim_diff = pred_ctmax - max_temp) %>% 
        select(date, daily_mean = mean_temp, daily_max = max_temp, species, pred_ctmax, lim_diff, doy)
      
      hind3_data = bind_rows(hind3_data, sp_data)
    }else{
      print(c(unique(sp_data$species), "Too many columns selected"))
    }
    
  }
  
  if(duration > 0){
    #Neither the prior day nor day of metrics should be used; use duration as n_days
    
    predictors = get_predictors(daily_values = hind_daily_temp_data, 
                                raw_temp = hind_temp_data, 
                                n_days = duration)
    
    parameter = preds_to_pull$Predictor[i]
    
    model_data = full_data %>%
      filter(sp_name %in% preds_to_pull$Species[i]) %>% 
      filter(sex == "female") %>% 
      mutate(collection_date = as_date(collection_date)) %>% 
      left_join(predictors, join_by(collection_date == date)) %>%  
      select(ctmax, contains(paste("day_", parameter, sep = "")))
    
    if(dim(model_data)[2] == 2){
      hind.model = lm(data = model_data, 
                      ctmax ~ .)
      
      sp_data = predictors %>% 
        select(date, contains(parameter)) %>% 
        mutate(pred_ctmax = predict(hind.model, newdata = .)) %>%  
        select(date, pred_ctmax) %>% 
        inner_join(hind_daily_temp_data, by = c("date")) %>% 
        mutate("species" = preds_to_pull$Species[i],
               "doy" = yday(date),
               lim_diff = pred_ctmax - max_temp) %>% 
        select(date, daily_mean = mean_temp, daily_max = max_temp, species, pred_ctmax, lim_diff, doy)
      
      hind3_data = bind_rows(hind3_data, sp_data)
      
    }else{
      print(c(unique(sp_data$species), "Too many columns selected"))
    }
    
  }
}


hind3_data = hind3_data %>% 
  mutate("method" = "Variable_acclimation")

This third approach did not affect the predicted patterns in Limnocalanus or Senecella (neither species has been observed in enough collections to estimate the effects of different environmental factors). Changing the acclimation approach did affect patterns in thermal limits in the other species though. The figure below shows how predicted warming tolerance varies over the year in the seven species, based on the three different prediction methods. In general, constant thermal limits (the ‘no acclimation’ method) resulted in larger warming tolerance during the winter and lower warming tolerance during the summer, although this effect was small in most species.

synthesis = bind_rows(
  select(hind1_data, date, doy, daily_mean, daily_max, species, "pred_ctmax" = mean_ctmax, lim_diff, method),
  select(hind2_data, date, doy, daily_mean, daily_max,  species, pred_ctmax, lim_diff, method),
  select(hind3_data, date, doy, daily_mean, daily_max,  species, pred_ctmax, lim_diff, method)) %>% 
  mutate(method = fct_relevel(method, "No_acclimation", "Constant_acclimation", "Variable_acclimation")) %>% 
  filter(!(species == "Osphranticum labronectum" & method == "Variable_acclimation"))

climatology = synthesis %>% 
  group_by(species, doy, method) %>%  
  summarise("mean_diff" = mean(lim_diff),
            "min_diff" = min(lim_diff),
            "max_diff" = max(lim_diff)) %>% 
  mutate(method = fct_relevel(method, "No_acclimation", "Constant_acclimation", "Variable_acclimation"))

acc_effects = synthesis %>% 
  pivot_wider(id_cols = c(date, species, doy), 
              names_from = method, 
              values_from = lim_diff) %>%  
  mutate("const_acc_effect" = Constant_acclimation - No_acclimation,
         "var_acc_effect" = Variable_acclimation - No_acclimation)

ggplot(synthesis, aes(x = doy, y = lim_diff, colour = method)) + 
  facet_wrap(species~.) + 
  geom_hline(yintercept = 0) + 
  geom_hline(yintercept = 5, colour = "grey") + 
  geom_point(alpha = 0.1) + 
  labs(x = "Day of Year", 
       y = "Predicted Warming Tolerance (°C Above Daily Max)") + 
  guides(colour = guide_legend(override.aes = list(alpha = 1))) + 
  theme_matt_facets(base_size = 18) + 
  theme(strip.text.x.top = element_text(size = 10))

wt_hindcast_summary = synthesis %>%  
  mutate("year" = year(date)) %>% 
  group_by(species, year, method) %>% 
  summarise("min_wt" = min(lim_diff),
            "max_wt" = max(lim_diff)) %>% 
  pivot_longer(cols = c(min_wt, max_wt), 
               names_to = "metric", 
               values_to = "wt") %>% 
  group_by(species, method, metric) %>% 
  summarise("mean_wt" = mean(wt))

wt_hindcast_summary %>% 
  filter(metric == "min_wt") %>% 
ggplot(aes(x = method, y = mean_wt, group = species, colour = species)) + 
  #facet_wrap(.~metric, scales = "free_y") + 
  geom_hline(yintercept = 0) + 
  geom_hline(yintercept = 5) + 
  geom_line(linewidth = 2) + 
  geom_point(size = 3) + 
  labs(x = "Scenario", 
       y = "Mean Yearly Minimum WT (°C)") + 
  scale_color_manual(values = species_cols) + 
  theme_matt_facets() + 
  theme(axis.text.x = element_text(angle = 300, hjust = 0, vjust = 0.5))

LS0tCnRpdGxlOiBTZWFzb25hbGl0eSBpbiBMYWtlIENoYW1wbGFpbiBDb3BlcG9kIFRoZXJtYWwgTGltaXRzCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgICAgICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICAgICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICAgICAgICB0b2M6IHRydWUKICAgICAgICAgIHRvY19mbG9hdDogdHJ1ZQogIGdpdGh1Yl9kb2N1bWVudDoKICAgICAgICAgIGh0bWxfcHJldmlldzogZmFsc2UKICAgICAgICAgIHRvYzogdHJ1ZQogICAgICAgICAgdG9jX2RlcHRoOiAzCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9VCwgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGLCBlY2hvID0gRn0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBrbml0cjo6aXNfaHRtbF9vdXRwdXQoKSwKICBmaWcuYWxpZ24gPSAiY2VudGVyIiwKICBmaWcucGF0aCA9ICIuLi9GaWd1cmVzL21hcmtkb3duLyIsCiAgZGV2ID0gYygicG5nIiwgInBkZiIpLAogIG1lc3NhZ2UgPSBGQUxTRSwKICB3YXJuaW5nID0gRkFMU0UsCiAgY29sbGFwc2UgPSBUCikKCnRoZW1lX21hdHQgPSBmdW5jdGlvbihiYXNlX3NpemUgPSAxOCwKICAgICAgICAgICAgICAgICAgICAgIGRhcmtfdGV4dCA9ICJncmV5MjAiKXsKICBtaWRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzJdCiAgbGlnaHRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzNdCiAgCiAgZ2dwdWJyOjp0aGVtZV9wdWJyKGJhc2VfZmFtaWx5PSJzYW5zIikgJStyZXBsYWNlJSAKICAgIHRoZW1lKAogICAgICBwYW5lbC5iYWNrZ3JvdW5kICA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksIAogICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLCAKICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLAogICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9ibGFuaygpLAogICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9IG1pZF90ZXh0LCBsaW5laGVpZ2h0ID0gMS4xKSwKICAgICAgdGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDEuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gZGFya190ZXh0KSwKICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBtaWRfdGV4dCksCiAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMS4yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gdW5pdChjKDMsIDAsIDAsIDApLCAibW0iKSksCiAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMS4yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gdW5pdChjKDAsIDUsIDAsIDApLCAibW0iKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbmdsZSA9IDkwKSwKICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT1iYXNlX3NpemUgKiAwLjkpLAogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDAuOSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlID0gImJvbGQiKSwKICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMC4yNSwgMC4yNSwgMC4yNSwgMC4yNSwiY20iKQogICAgKQp9Cgp0aGVtZV9tYXR0X2ZhY2V0cyA9IGZ1bmN0aW9uKGJhc2Vfc2l6ZSA9IDE4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhcmtfdGV4dCA9ICJncmV5MjAiKXsKICBtaWRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzJdCiAgbGlnaHRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzNdCiAgCiAgdGhlbWVfYncoYmFzZV9mYW1pbHk9InNhbnMiKSAlK3JlcGxhY2UlIAogICAgdGhlbWUoCiAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmJhY2tncm91bmQgID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwgCiAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksIAogICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksCiAgICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLAogICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9IG1pZF90ZXh0LCBsaW5laGVpZ2h0ID0gMS4xKSwKICAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUpLAogICAgICB0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMS41LAogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBkYXJrX3RleHQpLAogICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IG1pZF90ZXh0KSwKICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAxLjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMywgMCwgMCwgMCksICJtbSIpKSwKICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAxLjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMCwgNSwgMCwgMCksICJtbSIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuZ2xlID0gOTApLAogICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPWJhc2Vfc2l6ZSAqIDAuOSksCiAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMC45LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY2UgPSAiYm9sZCIpLAogICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLjI1LCAwLjI1LCAwLjI1LCAwLjI1LCJjbSIpCiAgICApCn0KCnNwZWNpZXNfY29scyA9IGMoIkxlcHRvZGlhcHRvbXVzIG1pbnV0dXMiID0gIiNmZmQwMjkiLAogICAgICAgICAgICAgICAgICJMZXB0b2RpYXB0b211cyBtaW51dHVzIGp1dmVuaWxlIiA9ICIjZTNkOGFmIiwKICAgICAgICAgICAgICAgICAiTGVwdG9kaWFwdG9tdXMgbWludXR1cyBtYWxlIiA9ICIjZmZlODk2IiwKICAgICAgICAgICAgICAgICAiTGVwdG9kaWFwdG9tdXMgc2ljaWxpcyIgPSAiI0Q4NkYyOSIsCiAgICAgICAgICAgICAgICAgIkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMgbWFsZSIgPSAiI0UyOEMwMCIsCiAgICAgICAgICAgICAgICAgIlNraXN0b2RpYXB0b211cyBzcCIgPSAiI0M1QzM1QSIsCiAgICAgICAgICAgICAgICAgIlNraXN0b2RpYXB0b211cyBzcCBtYWxlIiA9ICIjZDlkODkzIiwgCiAgICAgICAgICAgICAgICAgIlNraXN0b2RpYXB0b211cyBzcCBqdXZlbmlsZSIgPSAiI2U2ZTZhYSIsIAogICAgICAgICAgICAgICAgICJFcGlzY2h1cmEgbGFjdXN0cmlzIGp1dmVuaWxlIiA9ICJwbHVtMSIsIAogICAgICAgICAgICAgICAgICJFcGlzY2h1cmEgbGFjdXN0cmlzIG1hbGUiID0gInBsdW0zIiwgCiAgICAgICAgICAgICAgICAgIkVwaXNjaHVyYSBsYWN1c3RyaXMiID0gInBsdW00IiwgCiAgICAgICAgICAgICAgICAgIkxpbW5vY2FsYW51cyBtYWNydXJ1cyIgPSAic2t5Ymx1ZTQiLCAKICAgICAgICAgICAgICAgICAiTGltbm9jYWxhbnVzIG1hY3J1cnVzIG1hbGUiID0gInNreWJsdWUzIiwgCiAgICAgICAgICAgICAgICAgIkxpbW5vY2FsYW51cyBtYWNydXJ1cyBqdXZlbmlsZSIgPSAic2t5Ymx1ZSIsIAogICAgICAgICAgICAgICAgICJTZW5lY2VsbGEgY2FsYW5vaWRlcyIgPSAiZGFya3NlYWdyZWVuMyIsCiAgICAgICAgICAgICAgICAgIkxlcHRvZG9yYSBraW5kdGkgbWFsZSIgPSAibGlnaHRibHVlMyIsCiAgICAgICAgICAgICAgICAgIkxlcHRvZG9yYSBraW5kdGkiID0gImxpZ2h0Ymx1ZTQiLAogICAgICAgICAgICAgICAgICJMZXB0b2RvcmEga2luZHRpIGp1dmVuaWxlIiA9ICJsaWdodGJsdWUiLAogICAgICAgICAgICAgICAgICJPc3BocmFudGljdW0gbGFicm9uZWN0dW0iID0gImxpZ2h0Y29yYWwiKQpgYGAKCiMjIENvcGVwb2QgQ29sbGVjdGlvbgoKQ29wZXBvZHMgd2VyZSBjb2xsZWN0ZWQgYXQgYXBwcm94aW1hdGVseSB3ZWVrbHkgaW50ZXJ2YWxzIGZyb20gTGFrZSBDaGFtcGxhaW4gKEJ1cmxpbmd0b24gRmlzaGluZyBQaWVyKS4gUGxhbmt0b24gd2FzIGNvbGxlY3RlZCBmcm9tIHRoZSB0b3AgMyBtZXRlcnMgdXNpbmcgYSAyNTAgdW0gbWVzaCBuZXQuIAoKYGBge3J9CiMgIyBMYWtlIENoYW1wbGFpbiBuZWFyIEJ1cmxpbmd0b24sIFZUCiMgc2l0ZU51bWJlciA9ICIwNDI5NDUwMCIKIyBDaGFtcGxhaW5JbmZvID0gcmVhZE5XSVNzaXRlKHNpdGVOdW1iZXIpCiMgcGFyYW1ldGVyQ2QgPSAiMDAwMTAiCiMgc3RhcnREYXRlID0gIjIwMjMtMDEtMDEiCiMgZW5kRGF0ZSA9ICIyMDI0LTUtMjAiCiMgI3N0YXRDZCA9IGMoIjAwMDAxIiwgIjAwMDAyIiwiMDAwMDMiLCAiMDAwMTEiKSAjIDEgLSBtYXgsIDIgLSBtaW4sIDMgPSBtZWFuCiMgCiMgIyBDb25zdHJ1Y3RzIHRoZSBVUkwgZm9yIHRoZSBkYXRhIHdhbnRlZCB0aGVuIGRvd25sb2FkcyB0aGUgZGF0YQojIHVybCA9IGNvbnN0cnVjdE5XSVNVUkwoc2l0ZU51bWJlcnMgPSBzaXRlTnVtYmVyLCBwYXJhbWV0ZXJDZCA9IHBhcmFtZXRlckNkLAojICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnREYXRlID0gc3RhcnREYXRlLCBlbmREYXRlID0gZW5kRGF0ZSwgc2VydmljZSA9ICJ1diIpCiMgCiMgcmF3X3RlbXBzID0gaW1wb3J0V2F0ZXJNTDEodXJsLCBhc0RhdGVUaW1lID0gVCkgJT4lCiMgICBtdXRhdGUoImRhdGUiID0gYXMuRGF0ZShkYXRlVGltZSksCiMgICAgICAgICAgImhvdXIiID0gaG91cihkYXRlVGltZSkpICU+JQojICAgc2VsZWN0KGRhdGVUaW1lLCB0el9jZCwgZGF0ZSwgaG91ciwgZGVnQyA9IFhfMDAwMTBfMDAwMDApCiMgCiMgdGVtcF9kYXRhID0gIHJhd190ZW1wcyAlPiUKIyAgIHNlbGVjdChkYXRlLCBob3VyLCAidGVtcCIgPSBkZWdDKQojIAojIHdyaXRlLmNzdih0ZW1wX2RhdGEsIGZpbGUgPSAiLi9PdXRwdXQvRGF0YS9jaGFtcGxhaW5fdGVtcHMuY3N2Iiwgcm93Lm5hbWVzID0gRikKYGBgCgpDb2xsZWN0aW9ucyBiZWdhbiBpbiBsYXRlIE1heSAyMDIzLiBTZXZlcmFsIGdhcHMgYXJlIHByZXNlbnQsIGJ1dCBjb2xsZWN0aW9ucyBoYXZlIGNvbnRpbnVlZCBhdCByb3VnaGx5IHdlZWtseSBpbnRlcnZhbHMgc2luY2UgdGhlbi4gQ29wZXBvZHMgZnJvbSBgciBsZW5ndGgodW5pcXVlKGZ1bGxfZGF0YSRjb2xsZWN0aW9uX2RhdGUpKWAgY29sbGVjdGlvbnMgd2VyZSB1c2VkIHRvIG1ha2UgYSB0b3RhbCBvZiBgciBkaW0oZnVsbF9kYXRhKVsxXWAgdGhlcm1hbCBsaW1pdCBtZWFzdXJlbWVudHMuIE92ZXIgdGhpcyB0aW1lIHBlcmlvZCwgY29sbGVjdGlvbiB0ZW1wZXJhdHVyZXMgcmFuZ2VkIGZyb20gYHIgcGFzdGUobWluKGZ1bGxfZGF0YSRjb2xsZWN0aW9uX3RlbXApLCAiIHRvICIsIG1heChmdWxsX2RhdGEkY29sbGVjdGlvbl90ZW1wKSwgc2VwID0gIiIpYMKwQy4gICAgIAoKVGhlcmUgaXMgc3Vic3RhbnRpYWwgdmFyaWF0aW9uIGluIHRoZXJtYWwgbGltaXRzIGFjcm9zcyB0aGUgc3BlY2llcyBjb2xsZWN0ZWQuIFRoZXJlIGlzIGFsc28gc29tZSBkZWdyZWUgb2YgdmFyaWF0aW9uIHdpdGhpbiB0aGUgc3BlY2llcywgd2l0aCB0aGVybWFsIGxpbWl0cyBpbmNyZWFzaW5nIHNsaWdodGx5IGR1cmluZyB0aGUgc3VtbWVyLiAgICAKCmBgYHtyIG1haW4tZmlnLWN0bWF4LXRpbWVzZXJpZXMsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD01fQojIyBEYWlseSB2YWx1ZXMgZm9yIHRoZSBwZXJpb2QgZXhhbWluZWQgYnkgZGF0YXNldApjb2xsZWN0aW9uX2NvbmRpdGlvbnMgPSB0ZW1wX2RhdGEgJT4lCiAgdW5ncm91cCgpICU+JSAKICBncm91cF9ieShkYXRlKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5fdGVtcCA9IG1lYW4odGVtcCksCiAgICAgICAgICAgIG1lZF90ZW1wID0gbWVkaWFuKHRlbXApLAogICAgICAgICAgICB2YXJfdGVtcCA9IHZhcih0ZW1wKSwgCiAgICAgICAgICAgIG1pbl90ZW1wID0gbWluKHRlbXApLCAKICAgICAgICAgICAgbWF4X3RlbXAgPSBtYXgodGVtcCkpICU+JSAKICBtdXRhdGUoInJhbmdlX3RlbXAiID0gbWF4X3RlbXAgLSBtaW5fdGVtcCwKICAgICAgICAgZGF0ZSA9IGFzLkRhdGUoZGF0ZSkpICU+JSAKICB1bmdyb3VwKCkgJT4lICAKICBmaWx0ZXIoZGF0ZSA+PSAobWluKGFzLkRhdGUoZnVsbF9kYXRhJGNvbGxlY3Rpb25fZGF0ZSkpIC0gNykpICU+JSAKICBsZWZ0X2pvaW4odW5pcXVlKHNlbGVjdChmdWxsX2RhdGEsIGNvbGxlY3Rpb25fZGF0ZSwgY29sbGVjdGlvbl90ZW1wKSksIGJ5ID0gam9pbl9ieShkYXRlID09IGNvbGxlY3Rpb25fZGF0ZSkpCgojIyBNZWFuIGZlbWFsZSB0aGVybWFsIGxpbWl0cyBmb3IgZWFjaCBzcGVjaWVzLCBncm91cGVkIGJ5IGNvbGxlY3Rpb24Kc3BlY2llc19zdW1tYXJpZXMgPSBmdWxsX2RhdGEgJT4lICAKICAjZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAogIGdyb3VwX2J5KHNwX25hbWUsIGNvbGxlY3Rpb25fZGF0ZSwgY29sbGVjdGlvbl90ZW1wKSAlPiUgIAogIHN1bW1hcmlzZSgibWVhbl9jdG1heCIgPSBtZWFuKGN0bWF4KSwKICAgICAgICAgICAgInNhbXBsZV9zaXplIiA9IG4oKSwKICAgICAgICAgICAgImN0bWF4X3N0X2VyciIgPSAoc2QoY3RtYXgpIC8gc3FydChzYW1wbGVfc2l6ZSkpLAogICAgICAgICAgICAiY3RtYXhfdmFyIiA9IHZhcihjdG1heCksIAogICAgICAgICAgICAibWVhbl9zaXplIiA9IG1lYW4oc2l6ZSksCiAgICAgICAgICAgICJzaXplX3N0X2VyciIgPSAoc2Qoc2l6ZSkgLyBzcXJ0KHNhbXBsZV9zaXplKSksCiAgICAgICAgICAgICJzaXplX3ZhciIgPSB2YXIoc2l6ZSkpICU+JSAgCiAgdW5ncm91cCgpICU+JSAKICBjb21wbGV0ZShzcF9uYW1lLCBjb2xsZWN0aW9uX2RhdGUpICU+JSAKICBhcnJhbmdlKGRlc2Moc2FtcGxlX3NpemUpKQoKYWR1bHRfc3VtbWFyaWVzID0gZnVsbF9kYXRhICU+JSAgCiAgZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAogIGdyb3VwX2J5KHNwX25hbWUsIGNvbGxlY3Rpb25fZGF0ZSwgY29sbGVjdGlvbl90ZW1wKSAlPiUgIAogIHN1bW1hcmlzZSgibWVhbl9jdG1heCIgPSBtZWFuKGN0bWF4KSwKICAgICAgICAgICAgInNhbXBsZV9zaXplIiA9IG4oKSwKICAgICAgICAgICAgImN0bWF4X3N0X2VyciIgPSAoc2QoY3RtYXgpIC8gc3FydChzYW1wbGVfc2l6ZSkpLAogICAgICAgICAgICAiY3RtYXhfdmFyIiA9IHZhcihjdG1heCksIAogICAgICAgICAgICAibWVhbl9zaXplIiA9IG1lYW4oc2l6ZSksCiAgICAgICAgICAgICJzaXplX3N0X2VyciIgPSAoc2Qoc2l6ZSkgLyBzcXJ0KHNhbXBsZV9zaXplKSksCiAgICAgICAgICAgICJzaXplX3ZhciIgPSB2YXIoc2l6ZSkpICU+JSAgCiAgdW5ncm91cCgpICU+JSAKICBjb21wbGV0ZShzcF9uYW1lLCBjb2xsZWN0aW9uX2RhdGUpICU+JSAKICBhcnJhbmdlKGRlc2Moc2FtcGxlX3NpemUpKQoKCnRzZXJpZXNfZGF0YSA9IGZ1bGxfZGF0YSAlPiUgCiAgbXV0YXRlKHNwX25hbWUgPSBmY3RfcmVvcmRlcihzcF9uYW1lLCBjdG1heCwgLmRlc2MgPSBUKSkKCmdncGxvdCgpICsgCiAgZ2VvbV92bGluZShkYXRhID0gdW5pcXVlKHNlbGVjdCh0c2VyaWVzX2RhdGEsIGNvbGxlY3Rpb25fZGF0ZSkpLCAKICAgICAgICAgICAgIGFlcyh4aW50ZXJjZXB0ID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpKSwKICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5OTAiLAogICAgICAgICAgICAgbGluZXdpZHRoID0gMSkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IGNvbGxlY3Rpb25fY29uZGl0aW9ucywgCiAgICAgICAgICAgIGFlcyh4ID0gYXMuRGF0ZShkYXRlKSwgeSA9IG1lYW5fdGVtcCksCiAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIAogICAgICAgICAgICBsaW5ld2lkdGggPSAyKSArIAogICMgZ2VvbV9lcnJvcmJhcihkYXRhID0gc3BlY2llc19zdW1tYXJpZXMsCiAgIyAgICAgICAgICAgICAgIGFlcyh4ID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpLAogICMgICAgICAgICAgICAgICAgICAgeW1pbiA9IG1lYW5fY3RtYXggLSBjdG1heF9zdF9lcnIsIHltYXggPSBtZWFuX2N0bWF4ICsgY3RtYXhfc3RfZXJyLAogICMgICAgICAgICAgICAgICAgICAgY29sb3VyID0gc3BfbmFtZSksCiAgIyAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAxKSwKICAjICAgICAgICAgICAgICAgd2lkdGggPSA1LCBsaW5ld2lkdGggPSAxKSArCiAgIyBnZW9tX3BvaW50KGRhdGEgPSBhZHVsdF9zdW1tYXJpZXMsIAogICMgICAgICAgICAgICBhZXMoeCA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSwgeSA9IG1lYW5fY3RtYXgsIGNvbG91ciA9IHNwX25hbWUsIHNpemUgPSBzYW1wbGVfc2l6ZSkpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gdHNlcmllc19kYXRhLCAKICAgICAgICAgICAgIGFlcyh4ID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpLCB5ID0gY3RtYXgsIGNvbG91ciA9IHNwX25hbWUpLAogICAgICAgICAgICAgc2l6ZSA9IDIsIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMSwgaGVpZ2h0ID0gMCkpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgbGFicyh4ID0gIkRhdGUiLCAKICAgICAgIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLCAKICAgICAgIGNvbG91ciA9ICJTcGVjaWVzIiwKICAgICAgIHNpemUgPSAiU2FtcGxlIFNpemUiKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgpsYWtlX3RlbXBzID0gZ2dwbG90KCkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IGNvbGxlY3Rpb25fY29uZGl0aW9ucywgCiAgICAgICAgICAgIGFlcyh4ID0gYXMuRGF0ZShkYXRlKSwgeSA9IG1lYW5fdGVtcCksCiAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIAogICAgICAgICAgICBsaW5ld2lkdGggPSAxKSArIAogIGxhYnMoeCA9ICJEYXRlIiwgCiAgICAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwgCiAgICAgICBjb2xvdXIgPSAiU3BlY2llcyIsCiAgICAgICBzaXplID0gIlNhbXBsZSBTaXplIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQpgYGAKClRlbXBlcmF0dXJlcyBvYnNlcnZlZCBhdCB0aGUgdGltZSBvZiBjb2xsZWN0aW9uIGNsb3NlbHkgcmVzZW1ibGVkIHRoZSBtYXhpbXVtIGRhaWx5IHRlbXBlcmF0dXJlIGZyb20gdGhlIHRlbXBlcmF0dXJlIHNlbnNvciBkYXRhLiBNYXhpbXVtIHRlbXBlcmF0dXJlIHdhcyB1c2VkIGFzIGEgcHJveHkgaW5zdGVhZCBvZiBtZWFuIHRlbXBlcmF0dXJlIGFzIGNvbGxlY3Rpb25zIHdlcmUgdXN1YWxseSBtYWRlIGR1cmluZyBhZnRlcm5vb25zIG9yIGVhcmx5IGV2ZW5pbmdzLCBqdXN0IGZvbGxvd2luZyB0aGUgd2FybWVzdCBwYXJ0IG9mIHRoZSBkYXkuIAoKYGBge3Igc3VwcC1maWctdGVtcC1hY2MsIGZpZy53aWR0aCA9IDYsIGZpZy5oZWlnaHQ9Nn0KY29sbGVjdGlvbl9jb25kaXRpb25zICU+JSAKICBkcm9wX25hKGNvbGxlY3Rpb25fdGVtcCkgJT4lICAKICBnZ3Bsb3QoYWVzKHggPSBtYXhfdGVtcCwgeSA9IGNvbGxlY3Rpb25fdGVtcCkpICsgCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLAogICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEsIGNvbG91ciA9ICJncmV5IikgKyAKICBnZW9tX3BvaW50KHNpemUgPSAzKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoNSwxNSwyNSkpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGMoNSwxNSwyNSkpICsgCiAgbGFicyh4ID0gIk1heC4gVGVtcC4gZnJvbSBTZW5zb3IgKMKwQykiLAogICAgICAgeSA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIikgKyAKICB0aGVtZV9tYXR0KCkKYGBgCgpgYGB7ciBtaXNjLXJvdW5kLXN1bW1hcnktMiwgZmlnLndpZHRoPTExLCBmaWcuaGVpZ2h0PTExLCBpbmNsdWRlID0gRn0KZ2dwbG90KCkgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAKICAgICAgICAgICAgICAgYyhtYXgoZnVsbF9kYXRhJGNvbGxlY3Rpb25fdGVtcCksCiAgICAgICAgICAgICAgICAgbWluKGZ1bGxfZGF0YSRjb2xsZWN0aW9uX3RlbXApKSwgCiAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleTYwIiwKICAgICAgICAgICAgIGxpbmV3aWR0aCA9IGMoMiwxKSwgCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKyAKICBnZW9tX2JhcihkYXRhID0gdW5pcXVlKHNlbGVjdChmdWxsX2RhdGEsIGNvbGxlY3Rpb25fZGF0ZSwgY29sbGVjdGlvbl90ZW1wKSksIAogICAgICAgICAgIGFlcyh4ID0gYXNfZGF0ZShjb2xsZWN0aW9uX2RhdGUpLCB5ID0gY29sbGVjdGlvbl90ZW1wKSwKICAgICAgICAgICBzdGF0ID0gImlkZW50aXR5IiwKICAgICAgICAgICBmaWxsID0gImdyZXkzMCIpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gZnVsbF9kYXRhLCAKICAgICAgICAgICAgIGFlcyh4ID0gYXNfZGF0ZShjb2xsZWN0aW9uX2RhdGUpLCB5ID0gY3RtYXgpLAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjcsIGhlaWdodCA9IDApLAogICAgICAgICAgICAgY29sb3VyID0gImdyZXkzMCIsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKyAKICB5bGltKC0zLCA0MCkgKyAKICBjb29yZF9wb2xhcihzdGFydCA9IDApICsgCiAgdGhlbWVfdm9pZCgpCmBgYAoKClNpemUgYWxzbyB2YXJpZWQsIGJ1dCBwcmltYXJpbHkgYmV0d2VlbiByYXRoZXIgdGhhbiB3aXRoaW4gc3BlY2llcy4gCgpgYGB7ciBzdXBwLWZpZy1zaXplLXRpbWVzZXJpZXMsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD01fQpnZ3Bsb3QoKSArIAogIGdlb21fdmxpbmUoZGF0YSA9IHVuaXF1ZShzZWxlY3QoZnVsbF9kYXRhLCBjb2xsZWN0aW9uX2RhdGUpKSwgCiAgICAgICAgICAgICBhZXMoeGludGVyY2VwdCA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSksCiAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleTkwIiwKICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEpICsgCiAgZ2VvbV9saW5lKGRhdGEgPSBjb2xsZWN0aW9uX2NvbmRpdGlvbnMsIAogICAgICAgICAgICBhZXMoeCA9IGFzLkRhdGUoZGF0ZSksIHkgPSBtZWFuX3RlbXApLAogICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCAKICAgICAgICAgICAgbGluZXdpZHRoID0gMikgKyAKICAjIGdlb21fZXJyb3JiYXIoZGF0YSA9IHNwZWNpZXNfc3VtbWFyaWVzLAogICMgICAgICAgICAgICAgICBhZXMoeCA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSwgCiAgIyAgICAgICAgICAgICAgICAgICB5bWluID0gbWVhbl9jdG1heCAtIGN0bWF4X3N0X2VyciwgeW1heCA9IG1lYW5fY3RtYXggKyBjdG1heF9zdF9lcnIsCiAgIyAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBzcF9uYW1lKSwKICAjICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDEpLAogICMgICAgICAgICAgICAgICB3aWR0aCA9IDUsIGxpbmV3aWR0aCA9IDEpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gYWR1bHRfc3VtbWFyaWVzLCAKICAgICAgICAgICAgIGFlcyh4ID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpLCB5ID0gbWVhbl9zaXplICogNDAsIGNvbG91ciA9IHNwX25hbWUsIHNpemUgPSBzYW1wbGVfc2l6ZSksCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMSkpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKAogICAgbmFtZSA9ICJUZW1wZXJhdHVyZSIsICMgRmVhdHVyZXMgb2YgdGhlIGZpcnN0IGF4aXMKICAgIHNlYy5heGlzID0gc2VjX2F4aXMofi4vNDAsIG5hbWU9IlByb3NvbWUgTGVuZ3RoIChtbSkiKSwgIyBBZGQgYSBzZWNvbmQgYXhpcyBhbmQgc3BlY2lmeSBpdHMgZmVhdHVyZXMKICAgIGJyZWFrcyA9IGMoMCw1LDEwLDE1LDIwLDI1LDMwKQogICkgKyAKICBsYWJzKHggPSAiRGF0ZSIsIAogICAgICAgeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsIAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCmBgYAoKYGBge3IgbWlzYy10cmFpdC1kb3ktZmVhdHVyZSwgZmlnLndpZHRoID0gMTQsIGZpZy5oZWlnaHQgPSA3LCBpbmNsdWRlID0gRn0KI1Nob3duIGJlbG93IGlzIENUbWF4IGFuZCBib2R5IHNpemUgZm9yIHRoZSBzcGVjaWVzIHdpdGggdGhlIG1vc3QgZGF0YSAoKlNraXN0b2RpYXB0b211cyosICpMLiBtaW51dHVzKiwgKkwuIHNpY2lsaXMqLCBhbmQgKkVwaXNjaHVyYSopLCBwbG90dGVkIGFnYWluc3QgdGhlIGRheSBvZiB0aGUgeWVhciBmb3IgZWFjaCBzZXgvc3RhZ2Ugc2VwYXJhdGVseS4gCgpjdG1heF9mZWF0dXJlID0gZnVsbF9kYXRhICU+JSAgCiAgbXV0YXRlKGRveSA9IHlkYXkoY29sbGVjdGlvbl9kYXRlKSkgJT4lIAogIGZpbHRlcihzcF9uYW1lICVpbiUgYygiU2tpc3RvZGlhcHRvbXVzIG9yZWdvbmVuc2lzIiwgIkxlcHRvZGlhcHRvbXVzIG1pbnV0dXMiLCAiTGVwdG9kaWFwdG9tdXMgc2ljaWxpcyIsICJFcGlzY2h1cmEgbGFjdXN0cmlzIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBhcy5EYXRlKGNvbGxlY3Rpb25fZGF0ZSksIHkgPSBjdG1heCwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZmFjZXRfZ3JpZChzcF9uYW1lfnNleCkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICBsYWJzKHggPSAiRGF5IG9mIHRoZSBZZWFyIiwgCiAgICAgICB5ID0gIkNUbWF4ICjCsEMpIikgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwMCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKc2l6ZV9mZWF0dXJlID0gZnVsbF9kYXRhICU+JSAgCiAgbXV0YXRlKGRveSA9IHlkYXkoY29sbGVjdGlvbl9kYXRlKSkgJT4lIAogIGZpbHRlcihzcF9uYW1lICVpbiUgYygiU2tpc3RvZGlhcHRvbXVzIG9yZWdvbmVuc2lzIiwgIkxlcHRvZGlhcHRvbXVzIG1pbnV0dXMiLCAiTGVwdG9kaWFwdG9tdXMgc2ljaWxpcyIsICJFcGlzY2h1cmEgbGFjdXN0cmlzIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBhcy5EYXRlKGNvbGxlY3Rpb25fZGF0ZSksIHkgPSBzaXplLCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBmYWNldF9ncmlkKHNwX25hbWV+c2V4KSArIAogIGdlb21fcG9pbnQoKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIGxhYnMoeCA9ICJEYXkgb2YgdGhlIFllYXIiLCAKICAgICAgIHkgPSAiU2l6ZSAobW0pIikgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwMCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKZ2dhcnJhbmdlKGN0bWF4X2ZlYXR1cmUsIHNpemVfZmVhdHVyZSwgY29tbW9uLmxlZ2VuZCA9IFQsIGxlZ2VuZCA9ICJub25lIikKYGBgCgpgYGB7ciBzcC1vY2N1cmVuY2VzLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD01fQpzYW1wbGVfZGF0ZXNfcGxvdCA9IGZ1bGxfZGF0YSAlPiUgIAogIGZpbHRlcihzcF9uYW1lICE9ICJPc3BocmFudGljdW0gbGFicm9uZWN0dW0iKSAlPiUgCiAgbXV0YXRlKHNwX25hbWUgPSBhcy5mYWN0b3Ioc3BfbmFtZSksCiAgICAgICAgIHNwX25hbWUgPSBmY3RfcmVvcmRlcihzcF9uYW1lLCBjdG1heCkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBsdWJyaWRhdGU6OmFzX2RhdGUoY29sbGVjdGlvbl9kYXRlKSwgCiAgICAgICAgICAgICB5ID0gc3BfbmFtZSwgZmlsbCA9IHNwX25hbWUpKSArIAogICMgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYXNfZGF0ZSgKICAjICAgYygiMjAyMy0wNS0wMSIsCiAgIyAgICAgIjIwMjMtMDktMDEiLAogICMgICAgICIyMDI0LTAxLTAxIiwKICAjICAgICAiMjAyNC0wNS0wMSIpKSwKICAjICAgY29sb3VyID0gImdyZXkiLAogICMgICBsaW5ld2lkdGggPSAxKSArIAogIGdlb21fZGVuc2l0eV9yaWRnZXMoYmFuZHdpZHRoID0gMzAsCiAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXJlZF9wb2ludHMgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgIHBvaW50X3NoYXBlID0gMjEsCiAgICAgICAgICAgICAgICAgICAgICBwb2ludF9zaXplID0gMSwKICAgICAgICAgICAgICAgICAgICAgIHBvaW50X2NvbG91ciA9ICJncmV5MzAiLAogICAgICAgICAgICAgICAgICAgICAgcG9pbnRfYWxwaGEgPSAwLjgsCiAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuOCwKICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fcG9pbnRzX2ppdHRlcigKICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0ID0gMC4xLCB3aWR0aCA9IDApKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMyBtb250aHMiLAogICAgICAgICAgICAgICBkYXRlX2xhYmVscyA9ICIlYiIpICsgCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBsdWJyaWRhdGU6OmFzX2RhdGUoYygiMjAyMy0wNi0wOCIsICIyMDI0LTA1LTA4IikpKSArIAogIGxhYnMoeCA9ICJEYXkgb2YgWWVhciIsIAogICAgICAgeSA9ICJTcGVjaWVzIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICAjdGhlbWVfcmlkZ2VzKGdyaWQgPSBUKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCmBgYAoKVGhlIHNhbXBsZXMgY2FwdHVyZWQgdGhlIGJyb2FkIHNlYXNvbmFsIGNoYW5nZXMgaW4gY2FsYW5vaWQgY29wZXBvZCBjb21tdW5pdHkgY29tcG9zaXRpb24gaW4gdGhlIGxha2UuIFdlIG5vdGUsIGhvd2V2ZXIsIHRoYXQgcmFyZSBzcGVjaWVzIChlLmcuICpTZW5lY2VsbGEqIGFuZCAqTGltbm9jYWxhbnVzKikgd2VyZSBvZnRlbiBwcmVmZXJlbnRpYWxseSBzYW1wbGVkLCBzbyBhcmUgb3Zlci1yZXByZXNlbnRlZCBpbiB0aGUgZGF0YSBzZXQuIAoKYGBge3Igc3VwcC1maWctc3AtcHJvcHMsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0ID0gNSwgaW5jbHVkZSA9IEZ9CmFkdWx0X3N1bW1hcmllcyAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBtdXRhdGUoY29sbGVjdGlvbl9udW0gPSBhcy5udW1lcmljKGZhY3Rvcihjb2xsZWN0aW9uX2RhdGUpKSkgJT4lIAogIGdyb3VwX2J5KGNvbGxlY3Rpb25fZGF0ZSkgJT4lICAKICBhcnJhbmdlKGNvbGxlY3Rpb25fZGF0ZSkgJT4lIAogIHNlbGVjdChzcF9uYW1lLCBjb2xsZWN0aW9uX2RhdGUsIGNvbGxlY3Rpb25fbnVtLCBzYW1wbGVfc2l6ZSkgJT4lIAogIG11dGF0ZShzYW1wbGVfc2l6ZSA9IHJlcGxhY2VfbmEoc2FtcGxlX3NpemUsIDApKSAlPiUgCiAgbXV0YXRlKHRvdGFsID0gc3VtKHNhbXBsZV9zaXplKSwKICAgICAgICAgcGVyY2VudGFnZSA9IHNhbXBsZV9zaXplIC8gdG90YWwsCiAgICAgICAgIGNvbGxlY3Rpb25fZGF0ZSA9IGx1YnJpZGF0ZTo6YXNfZGF0ZShjb2xsZWN0aW9uX2RhdGUpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gY29sbGVjdGlvbl9kYXRlLCB5ID0gcGVyY2VudGFnZSwgZmlsbCA9IHNwX25hbWUpKSArIAogIGdlb21fYXJlYSgpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBjKDAsMSkpICsgCiAgbGFicyh4ID0gIkNvbGxlY3Rpb24gRGF0ZSIsIAogICAgICAgeSA9ICJQcm9wb3J0aW9uIiwgCiAgICAgICBmaWxsID0gIlNwZWNpZXMiKSArIAogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMjApICsgCiAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKCkpCmBgYAoKVGhyb3VnaG91dCB0aGUgc2Vhc29uLCB0aGUgcHJldmFsZW5jZSBvZiB2YXJpb3VzIHVuaWRlbnRpZmllZCBwYXRob2dlbnMgYWxzbyB2YXJpZWQsIHdpdGggdmVyeSBsaXR0bGUgaW5mZWN0aW9uIG9ic2VydmVkIGR1cmluZyB0aGUgV2ludGVyIGFuZCBTcHJpbmcuIAoKYGBge3Igc3VwcC1maWctcGF0aG9nZW4tcHJvcHMsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTV9CnBhdGhvZ2VuX2NvbHMgPSBjKCJubyIgPSAiZ3JleTk1IiwgImNsb3VkeSIgPSAiaG9uZXlkZXczIiwgInNwb3QiID0gImFudGlxdWV3aGl0ZTMiLCAib3RoZXIiID0gInRvbWF0bzMiKQoKZnVsbF9kYXRhICU+JSAKICBzZWxlY3QoY29sbGVjdGlvbl9kYXRlLCBkZXZfZWdncywgcGF0aG9nZW4sIGxpcGlkcywgc3BfbmFtZSwgc2V4KSAlPiUgCiAgZ3JvdXBfYnkoKSAlPiUgCiAgZmlsdGVyKHNleCAhPSAianV2ZW5pbGUiKSAlPiUgCiAgZ3JvdXBfYnkoY29sbGVjdGlvbl9kYXRlKSAlPiUgCiAgY291bnQocGF0aG9nZW4pICU+JSAKICBmaWx0ZXIocGF0aG9nZW4gIT0gInVuY2VydGFpbiIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gImNvbGxlY3Rpb25fZGF0ZSIsIAogICAgICAgICAgICAgIG5hbWVzX2Zyb20gPSBwYXRob2dlbiwgCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSBuLAogICAgICAgICAgICAgIHZhbHVlc19maWxsID0gMCkgJT4lIAogIG11dGF0ZSh0b3RhbCA9IHN1bShubywgY2xvdWR5LCBzcG90LCBvdGhlcikpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGMobm8sIGNsb3VkeSwgc3BvdCwgb3RoZXIpLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJwYXRob2dlbiIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUgCiAgbXV0YXRlKHBlcmNlbnQgPSBjb3VudC90b3RhbCwKICAgICAgICAgY29sbGVjdGlvbl9kYXRlID0gbHVicmlkYXRlOjphc19kYXRlKGNvbGxlY3Rpb25fZGF0ZSksCiAgICAgICAgIHBhdGhvZ2VuID0gZmN0X3JlbGV2ZWwocGF0aG9nZW4sICJubyIsICJjbG91ZHkiLCAic3BvdCIsICJvdGhlciIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gY29sbGVjdGlvbl9kYXRlLCB5ID0gcGVyY2VudCwgZmlsbCA9IHBhdGhvZ2VuKSkgKyAKICBnZW9tX2FyZWEoKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhdGhvZ2VuX2NvbHMpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGMoMCwxKSkgKyAKICBsYWJzKHggPSAiQ29sbGVjdGlvbiBEYXRlIiwgCiAgICAgICB5ID0gIlByb3BvcnRpb24iLCAKICAgICAgIGZpbGwgPSAiUGF0aG9nZW4iKSArIAogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMjApICsgCiAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKCkpCmBgYAoKVGhlIHRyYW5zcGFyZW50IGJvZGllcyBvZiB0aGVzZSBjb3BlcG9kcyBhbHNvIGFsbG93ZWQgdXMgdG8gZXhhbWluZSBzZWFzb25hbCBwYXR0ZXJucyBpbiBsaXBpZCByZXNlcnZlcyBhbmQgaW4gdGhlIHByb2R1Y3Rpb24gb2YgZWdncy4gTWF0dXJpbmcgb29jeXRlcyBhcmUgdmlzaWJsZSBpbiBmZW1hbGUgY29wZXBvZHMgYmVmb3JlIHRoZXkgYXJlIHJlbGVhc2VkLiBUaGVyZSB3YXMgbm8gc3Ryb25nIHNlYXNvbmFsIGN5Y2xlIGluIHRoZSBwcm9kdWN0aW9uIG9mIHRoZXNlIGVnZ3MgaW4gYW55IHNwZWNpZXMsIGFuZCBpbnN0ZWFkLCBmZW1hbGVzIHdlcmUgcmVwcm9kdWN0aXZlbHkgYWN0aXZlIHRocm91Z2hvdXQgdGhlaXIgcmVzcGVjdGl2ZSBzZWFzb25zIG9mIG9jY3VyZW5jZS4gCgpgYGB7ciBzdXBwLWZpZy1kZXZlZ2dzLXByb3BzLCBmaWcuaGVpZ2h0ID0gMTUsIGZpZy53aWR0aCA9IDh9CmRldl9lZ2dzX2NvbHMgPSBjKCJubyIgPSAiZ3JleTk1IiwgInllcyIgPSAibGlnaHRibHVlMyIpCgpmdWxsX2RhdGEgJT4lIAogIHNlbGVjdChjb2xsZWN0aW9uX2RhdGUsIGRldl9lZ2dzLCBwYXRob2dlbiwgbGlwaWRzLCBzcF9uYW1lLCBzZXgpICU+JSAKICBncm91cF9ieShzcF9uYW1lKSAlPiUgCiAgZmlsdGVyKHNleCAhPSAianV2ZW5pbGUiKSAlPiUgCiAgZ3JvdXBfYnkoc3BfbmFtZSwgY29sbGVjdGlvbl9kYXRlKSAlPiUgCiAgY291bnQoZGV2X2VnZ3MpICU+JSAKICBmaWx0ZXIoZGV2X2VnZ3MgIT0gInVuY2VydGFpbiIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYygiY29sbGVjdGlvbl9kYXRlIiwgInNwX25hbWUiKSwgCiAgICAgICAgICAgICAgbmFtZXNfZnJvbSA9IGRldl9lZ2dzLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IG4sCiAgICAgICAgICAgICAgdmFsdWVzX2ZpbGwgPSAwKSAlPiUgCiAgbXV0YXRlKHRvdGFsID0gc3VtKG5vLCB5ZXMpKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKG5vLCB5ZXMpLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJkZXZfZWdncyIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUgCiAgbXV0YXRlKHBlcmNlbnQgPSBjb3VudC90b3RhbCwKICAgICAgICAgY29sbGVjdGlvbl9kYXRlID0gbHVicmlkYXRlOjphc19kYXRlKGNvbGxlY3Rpb25fZGF0ZSksCiAgICAgICAgIGRldl9lZ2dzID0gZmN0X3JlbGV2ZWwoZGV2X2VnZ3MsICJubyIsICJ5ZXMiKSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgY29tcGxldGUoY29sbGVjdGlvbl9kYXRlLCBuZXN0aW5nKHNwX25hbWUsIGRldl9lZ2dzKSwgZmlsbCA9IGxpc3QocGVyY2VudCA9IDEpKSAlPiUgCiAgbXV0YXRlKHBlcmNlbnQgPSBpZl9lbHNlKGlzLm5hKHRvdGFsKSAmIGRldl9lZ2dzID09ICJ5ZXMiLCAwLCBwZXJjZW50KSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGNvbGxlY3Rpb25fZGF0ZSwgeSA9IHBlcmNlbnQsIGZpbGwgPSBkZXZfZWdncykpICsgCiAgZmFjZXRfd3JhcChzcF9uYW1lfi4sIG5jb2wgPSAxKSArIAogIGdlb21fYXJlYSgpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gZGV2X2VnZ3NfY29scykgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygwLDEpKSArIAogIGxhYnMoeCA9ICJDb2xsZWN0aW9uIERhdGUiLCAKICAgICAgIHkgPSAiUHJvcG9ydGlvbiIsIAogICAgICAgZmlsbCA9ICJEZXZlbG9waW5nIFxuRWdncyIpICsgCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAyMCkgKyAKICB0aGVtZShwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUoKSkKYGBgCgpUaGUgcHJlc2VuY2Ugb2YgbGlwaWRzIHZhcmllZCBhY3Jvc3Mgc3BlY2llcywgd2l0aCBvbmx5ICpMLiBtaW51dHVzKiwgKkwuIHNpY2lsaXMqLCBhbmQgKkxpbW5vY2FsYW51cyogcmVndWxhcmx5IHBvc3Nlc3NpbmcgbGlwaWQgc3RvcmVzLiAKCmBgYHtyIHN1cHAtZmlnLWxpcGlkcy1wcm9wcywgZmlnLmhlaWdodCA9IDE1LCBmaWcud2lkdGggPSA4fQpsaXBpZF9jb2xzID0gYygibm8iID0gImdyZXk5NSIsICJ5ZXMiID0gInNpZW5uYTIiKQoKZnVsbF9kYXRhICU+JSAKICBzZWxlY3QoY29sbGVjdGlvbl9kYXRlLCBkZXZfZWdncywgcGF0aG9nZW4sIGxpcGlkcywgc3BfbmFtZSwgc2V4KSAlPiUgCiAgZ3JvdXBfYnkoc3BfbmFtZSkgJT4lIAogIGZpbHRlcihzZXggIT0gImp1dmVuaWxlIikgJT4lIAogIGdyb3VwX2J5KHNwX25hbWUsIGNvbGxlY3Rpb25fZGF0ZSkgJT4lIAogIGNvdW50KGxpcGlkcykgJT4lIAogIGZpbHRlcihsaXBpZHMgIT0gInVuY2VydGFpbiIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYygiY29sbGVjdGlvbl9kYXRlIiwgInNwX25hbWUiKSwgCiAgICAgICAgICAgICAgbmFtZXNfZnJvbSA9IGxpcGlkcywgCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSBuLAogICAgICAgICAgICAgIHZhbHVlc19maWxsID0gMCkgJT4lIAogIG11dGF0ZSh0b3RhbCA9IHN1bShubywgeWVzKSkgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gYyhubywgeWVzKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAibGlwaWRzIiwgCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJjb3VudCIpICU+JSAKICBtdXRhdGUocGVyY2VudCA9IGNvdW50L3RvdGFsLAogICAgICAgICBjb2xsZWN0aW9uX2RhdGUgPSBsdWJyaWRhdGU6OmFzX2RhdGUoY29sbGVjdGlvbl9kYXRlKSwKICAgICAgICAgbGlwaWRzID0gZmN0X3JlbGV2ZWwobGlwaWRzLCAibm8iLCAieWVzIikpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGNvbXBsZXRlKGNvbGxlY3Rpb25fZGF0ZSwgbmVzdGluZyhzcF9uYW1lLCBsaXBpZHMpLCBmaWxsID0gbGlzdChwZXJjZW50ID0gMSkpICU+JSAKICBtdXRhdGUocGVyY2VudCA9IGlmX2Vsc2UoaXMubmEodG90YWwpICYgbGlwaWRzID09ICJ5ZXMiLCAwLCBwZXJjZW50KSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGNvbGxlY3Rpb25fZGF0ZSwgeSA9IHBlcmNlbnQsIGZpbGwgPSBsaXBpZHMpKSArIAogIGZhY2V0X3dyYXAoc3BfbmFtZX4uLCBuY29sID0gMSkgKyAKICBnZW9tX2FyZWEoKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGxpcGlkX2NvbHMpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGMoMCwxKSkgKyAKICBsYWJzKHggPSAiQ29sbGVjdGlvbiBEYXRlIiwgCiAgICAgICB5ID0gIlByb3BvcnRpb24iLCAKICAgICAgIGZpbGwgPSAiTGlwaWRzXG5QcmVzZW50IikgKyAKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDIwKSArIAogIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZSgpKQpgYGAKCgojIyBUZW1wZXJhdHVyZSBWYXJpYWJpbGl0eQpMYWtlIENoYW1wbGFpbiBpcyBoaWdobHkgc2Vhc29uYWwsIHdpdGggYm90aCBhdmVyYWdlIHRlbXBlcmF0dXJlcyBhbmQgdGVtcGVyYXR1cmUgdmFyaWFiaWxpdHkgY2hhbmdpbmcgdGhyb3VnaG91dCB0aGUgeWVhci4gVGhlc2UgcGF0dGVybnMgaW4gdGhlIGV4cGVyaWVuY2VkIHRoZXJtYWwgZW52aXJvbm1lbnQgbWF5IGRyaXZlIHRoZSBvYnNlcnZlZCB2YXJpYXRpb24gaW4gY29wZXBvZCB0aGVybWFsIGxpbWl0cy4gSG93ZXZlciwgdGhlIHRpbWUgcGVyaW9kIGFmZmVjdGluZyBjb3BlcG9kIHRoZXJtYWwgbGltaXRzIGlzIHVua25vd24uIERlcGVuZGluZyB0aGUgb24gdGhlIGR1cmF0aW9uIG9mIHRpbWUgY29uc2lkZXJlZCwgdGhlcmUgYXJlIGxhcmdlIGNoYW5nZXMgaW4gdGhlIGV4cGVyaWVuY2VkIGVudmlyb25tZW50LCBpbiBwYXJ0aWN1bGFyIHJlZ2FyZGluZyB0aGUgdGVtcGVyYXR1cmUgcmFuZ2UgYW5kIHZhcmlhbmNlLiBDb25zaWRlciBmb3IgZXhhbXBsZSB0aHJlZSB0aW1lIHBlcmlvZHM6IHRoZSBkYXkgb2YgY29sbGVjdGlvbiwgb25lIHdlZWsgcHJpb3IgdG8gY29sbGVjdGlvbiwgYW5kIGZvdXIgd2Vla3MgcHJpb3IgdG8gY29sbGVjdGlvbi4gV2hpbGUgdGhlIG92ZXJhbGwgcGF0dGVybiBpcyBzaW1pbGFyLCB3ZSBjYW4gc2VlIHRoYXQsIHVuc3VycHJpc2luZ2x5LCBjb25zaWRlcmluZyBsb25nZXIgcGVyaW9kcyBvZiB0aW1lIHJlc3VsdHMgaW4gbGFyZ2VyIHJhbmdlcyBhbmQgc2xpZ2h0bHkgY2hhbmdlcyB0aGUgcGF0dGVybiBvZiB2YXJpYW5jZSBleHBlcmllbmNlZC4gCgpgYGB7ciBkYWlseS10ZW1wLWRhdGEsIGluY2x1ZGUgPSBGfQojIyBEYWlseSB2YWx1ZXMKZGFpbHlfdGVtcF9kYXRhID0gdGVtcF9kYXRhICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lIAogIHN1bW1hcmlzZShtZWFuX3RlbXAgPSBtZWFuKHRlbXApLAogICAgICAgICAgICBtZWRfdGVtcCA9IG1lZGlhbih0ZW1wKSwKICAgICAgICAgICAgdmFyX3RlbXAgPSB2YXIodGVtcCksIAogICAgICAgICAgICBtaW5fdGVtcCA9IG1pbih0ZW1wKSwgCiAgICAgICAgICAgIG1heF90ZW1wID0gbWF4KHRlbXApKSAlPiUgCiAgbXV0YXRlKCJyYW5nZV90ZW1wIiA9IG1heF90ZW1wIC0gbWluX3RlbXApCgpkYXlfcHJpb3JfdGVtcF9kYXRhID0gdGVtcF9kYXRhICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGdyb3VwX2J5KGRhdGUpICU+JSAKICBzdW1tYXJpc2UobWVhbl90ZW1wID0gbWVhbih0ZW1wKSwKICAgICAgICAgICAgbWVkX3RlbXAgPSBtZWRpYW4odGVtcCksCiAgICAgICAgICAgIHZhcl90ZW1wID0gdmFyKHRlbXApLCAKICAgICAgICAgICAgbWluX3RlbXAgPSBtaW4odGVtcCksIAogICAgICAgICAgICBtYXhfdGVtcCA9IG1heCh0ZW1wKSkgJT4lIAogIG11dGF0ZShkYXRlID0gZGF0ZSArIDEpICU+JSAKICByZW5hbWVfd2l0aCguZm4gPSB+IHBhc3RlMCgicHJpb3JfZGF5XyIsIC54KSwgLmNvbHMgPSBjKC1kYXRlKSkKCmRhaWx5X3Bsb3QgPSBkYWlseV90ZW1wX2RhdGEgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gYygtZGF0ZSksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInBhcmFtZXRlciIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAidGVtcCIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkYXRlLCB5ID0gdGVtcCwgY29sb3VyID0gcGFyYW1ldGVyKSkgKyAKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoCiAgICAibWVhbl90ZW1wIiA9ICJvbGl2ZWRyYWIzIiwKICAgICJtZWRfdGVtcCIgPSAic2VhZ3JlZW4zIiwKICAgICJtYXhfdGVtcCIgPSAidG9tYXRvIiwgIAogICAgIm1pbl90ZW1wIiA9ICJkb2RnZXJibHVlIiwKICAgICJyYW5nZV90ZW1wIiA9ICJnb2xkZW5yb2QzIiwKICAgICJ2YXJfdGVtcCIgPSAiZGFya2dvbGRlbnJvZDEiCiAgKSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYXMuRGF0ZShjKCIyMDIzLTAxLTAxIiwgIjIwMjMtMDQtMDEiLCAiMjAyMy0wNy0wMSIpKSkgKyAKICBnZ3RpdGxlKCJEYWlseSBWYWx1ZXMiKSArIAogIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsCiAgICAgICB4ID0gIiIpICsgCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMjApICsgCiAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCmBgYAoKYGBge3IgcHJlZGljdG9ycy1mdW5jdGlvbn0KIyMgRGVmaW5pbmcgdGhlIGZ1bmN0aW9uIHRvIGdldCBwcmVkaWN0b3IgdmFsdWVzIGZvciBwZXJpb2RzIG9mIGRpZmZlcmVudCBsZW5ndGhzCmdldF9wcmVkaWN0b3JzID0gZnVuY3Rpb24oZGFpbHlfdmFsdWVzLCByYXdfdGVtcCwgbl9kYXlzKXsKICBwcmVmaXggPSBzdHJfcmVwbGFjZV9hbGwoeGZ1bjo6bnVtYmVyc190b193b3JkcyhuX2RheXMpLCBwYXR0ZXJuID0gIiAiLCByZXBsYWNlbWVudCA9ICItIikKICAKICBtZWFuX3ZhbHVlcyA9IGRhaWx5X3ZhbHVlcyAlPiUgCiAgICB1bmdyb3VwKCkgJT4lIAogICAgbXV0YXRlKG1lYW5fbWF4ID0gc2xpZGVfdmVjKC54ID0gbWF4X3RlbXAsIC5mID0gbWVhbiwgLmJlZm9yZSA9IG5fZGF5cywgLmNvbXBsZXRlID0gVCksCiAgICAgICAgICAgbWVhbl9taW4gPSBzbGlkZV92ZWMoLnggPSBtaW5fdGVtcCwgLmYgPSBtZWFuLCAuYmVmb3JlID0gbl9kYXlzLCAuY29tcGxldGUgPSBUKSwKICAgICAgICAgICBtZWFuX3JhbmdlID0gc2xpZGVfdmVjKC54ID0gcmFuZ2VfdGVtcCwgLmYgPSBtZWFuLCAuYmVmb3JlID0gbl9kYXlzLCAuY29tcGxldGUgPSBUKSkgJT4lIAogICAgc2VsZWN0KGRhdGUsIG1lYW5fbWF4LCBtZWFuX21pbiwgbWVhbl9yYW5nZSkgJT4lIAogICAgcmVuYW1lX3dpdGgoIH4gcGFzdGUocHJlZml4LCAiZGF5IiwgLngsIHNlcCA9ICJfIiksIC5jb2xzID0gYygtZGF0ZSkpCiAgCiAgcGVyaW9kX3ZhbHVlcyA9IHJhd190ZW1wICU+JSAKICAgIG11dGF0ZShtZWFuID0gc2xpZGVfaW5kZXhfbWVhbih0ZW1wLCBpID0gZGF0ZSwgYmVmb3JlID0gZGF5cyhuX2RheXMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYV9ybSA9IFQpLAogICAgICAgICAgIG1heCA9IHNsaWRlX2luZGV4X21heCh0ZW1wLCBpID0gZGF0ZSwgYmVmb3JlID0gZGF5cyhuX2RheXMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFfcm0gPSBUKSwKICAgICAgICAgICBtaW4gPSBzbGlkZV9pbmRleF9taW4odGVtcCwgaSA9IGRhdGUsIGJlZm9yZSA9IGRheXMobl9kYXlzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFfcm0gPSBUKSwKICAgICAgICAgICBtZWQgPSBzbGlkZV9pbmRleF9kYmwodGVtcCwgLmkgPSBkYXRlLCAuYmVmb3JlID0gZGF5cyhuX2RheXMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFfcm0gPSBULCAuZiA9IG1lZGlhbiksCiAgICAgICAgICAgdmFyID0gc2xpZGVfaW5kZXhfZGJsKHRlbXAsIC5pID0gZGF0ZSwgLmJlZm9yZSA9IGRheXMobl9kYXlzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5mID0gdmFyKSwKICAgICAgICAgICByYW5nZSA9IG1heCAtIG1pbikgJT4lICAKICAgIHNlbGVjdCgtdGVtcCkgJT4lICAKICAgIGRpc3RpbmN0KCkgJT4lIAogICAgcmVuYW1lX3dpdGgoIH4gcGFzdGUocHJlZml4LCAiZGF5IiwgLngsIHNlcCA9ICJfIiksIC5jb2xzID0gYygtZGF0ZSkpJT4lIAogICAgaW5uZXJfam9pbihtZWFuX3ZhbHVlcywgYnkgPSBjKCJkYXRlIikpICU+JSAgCiAgICBkcm9wX25hKCkKICAKICByZXR1cm4ocGVyaW9kX3ZhbHVlcykKfQpgYGAKCmBgYHtyIG1pc2MtcHJlZGljdG9ycy1hbmQtcGxvdHMsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD01LCBpbmNsdWRlID0gRn0KIyAjIyBHZXR0aW5nIHByZWRpY3RvciB2YXJpYWJsZXMgZm9yIGRpZmZlcmVudCBwZXJpb2RzCiMgCiMgIyMjIFNob3J0ICh0aHJlZSBkYXlzKQojIHRocmVlX2RheV90ZW1wcyA9IGdldF9wcmVkaWN0b3JzKGRhaWx5X3ZhbHVlcyA9IGRhaWx5X3RlbXBfZGF0YSwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3X3RlbXAgPSB0ZW1wX2RhdGEsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5fZGF5cyA9IDMpCiMgCiMgIyMjIE9ORSBXRUVLCndlZWtfdGVtcHMgPSBnZXRfcHJlZGljdG9ycyhkYWlseV92YWx1ZXMgPSBkYWlseV90ZW1wX2RhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfdGVtcCA9IHRlbXBfZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5fZGF5cyA9IDcpCgp3ZWVrX3Bsb3QgPSB3ZWVrX3RlbXBzICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYygtZGF0ZSksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInBhcmFtZXRlciIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJ0ZW1wIikgJT4lCiAgZmlsdGVyKHBhcmFtZXRlciAlaW4lIGMoInNldmVuX2RheV9tZWFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAic2V2ZW5fZGF5X21lZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgInNldmVuX2RheV9tYXgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICJzZXZlbl9kYXlfbWluIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAic2V2ZW5fZGF5X3ZhciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgInNldmVuX2RheV9yYW5nZSIpKSAlPiUKICBtdXRhdGUocGFyYW1ldGVyID0gcGFzdGUod29yZChwYXJhbWV0ZXIsIHN0YXJ0ID0gMywgc2VwID0gZml4ZWQoIl8iKSksICJfdGVtcCIsIHNlcCA9ICIiKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IHRlbXAsIGNvbG91ciA9IHBhcmFtZXRlcikpICsKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygKICAgICJtZWFuX3RlbXAiID0gIm9saXZlZHJhYjMiLAogICAgIm1lZF90ZW1wIiA9ICJzZWFncmVlbjMiLAogICAgIm1heF90ZW1wIiA9ICJ0b21hdG8iLAogICAgIm1pbl90ZW1wIiA9ICJkb2RnZXJibHVlIiwKICAgICJyYW5nZV90ZW1wIiA9ICJnb2xkZW5yb2QzIiwKICAgICJ2YXJfdGVtcCIgPSAiZGFya2dvbGRlbnJvZDEiCiAgKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBhcy5EYXRlKGMoIjIwMjMtMDEtMDEiLCAiMjAyMy0wNC0wMSIsICIyMDIzLTA3LTAxIikpKSArCiAgZ2d0aXRsZSgiT25lIFdlZWsiKSArCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgICAgIHggPSAiIikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDIwKSArCiAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCiMgCiMgCiMgIyMjIFRXTyBXRUVLUwojIHR3b193ZWVrX3RlbXBzID0gZ2V0X3ByZWRpY3RvcnMoZGFpbHlfdmFsdWVzID0gZGFpbHlfdGVtcF9kYXRhLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd190ZW1wID0gdGVtcF9kYXRhLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5fZGF5cyA9IDE0KQojIAojIHR3b193ZWVrX3Bsb3QgPSB0d29fd2Vla190ZW1wcyAlPiUgCiMgICBwaXZvdF9sb25nZXIoY29scyA9IGMoLWRhdGUpLAojICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInBhcmFtZXRlciIsIAojICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJ0ZW1wIikgJT4lIAojICAgZmlsdGVyKHBhcmFtZXRlciAlaW4lIGMoImZvdXJ0ZWVuX2RheV9tZWFuIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3VydGVlbl9kYXlfbWVkIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3VydGVlbl9kYXlfbWF4IiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm91cnRlZW5fZGF5X21pbiIsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvdXJ0ZWVuX2RheV92YXIiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvdXJ0ZWVuX2RheV9yYW5nZSIpKSAlPiUgCiMgICBtdXRhdGUocGFyYW1ldGVyID0gcGFzdGUod29yZChwYXJhbWV0ZXIsIHN0YXJ0ID0gMywgc2VwID0gZml4ZWQoIl8iKSksICJfdGVtcCIsIHNlcCA9ICIiKSkgJT4lIAojICAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IHRlbXAsIGNvbG91ciA9IHBhcmFtZXRlcikpICsgCiMgICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKyAKIyAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygKIyAgICAgIm1lYW5fdGVtcCIgPSAib2xpdmVkcmFiMyIsCiMgICAgICJtZWRfdGVtcCIgPSAic2VhZ3JlZW4zIiwKIyAgICAgIm1heF90ZW1wIiA9ICJ0b21hdG8iLCAgCiMgICAgICJtaW5fdGVtcCIgPSAiZG9kZ2VyYmx1ZSIsCiMgICAgICJyYW5nZV90ZW1wIiA9ICJnb2xkZW5yb2QzIiwKIyAgICAgInZhcl90ZW1wIiA9ICJkYXJrZ29sZGVucm9kMSIKIyAgICkpICsgCiMgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYXMuRGF0ZShjKCIyMDIzLTAxLTAxIiwgIjIwMjMtMDQtMDEiLCAiMjAyMy0wNy0wMSIpKSkgKyAKIyAgIGdndGl0bGUoIlR3byBXZWVrcyIpICsgCiMgICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAojICAgICAgICB4ID0gIiIpICsgCiMgICB0aGVtZV9idyhiYXNlX3NpemUgPSAyMCkgKyAKIyAgIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiMgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCiMgCiMgCiMgIyMjIEZPVVIgV0VFS1MKZm91cl93ZWVrX3RlbXBzID0gZ2V0X3ByZWRpY3RvcnMoZGFpbHlfdmFsdWVzID0gZGFpbHlfdGVtcF9kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfdGVtcCA9IHRlbXBfZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbl9kYXlzID0gMjgpCgpmb3VyX3dlZWtfcGxvdCA9IGZvdXJfd2Vla190ZW1wcyAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoLWRhdGUpLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJwYXJhbWV0ZXIiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAidGVtcCIpICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgJWluJSBjKCJ0d2VudHktZWlnaHRfZGF5X21lYW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICJ0d2VudHktZWlnaHRfZGF5X21lZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgInR3ZW50eS1laWdodF9kYXlfbWF4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAidHdlbnR5LWVpZ2h0X2RheV9taW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICJ0d2VudHktZWlnaHRfZGF5X3ZhciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgInR3ZW50eS1laWdodF9kYXlfcmFuZ2UiKSkgJT4lCiAgbXV0YXRlKHBhcmFtZXRlciA9IHBhc3RlKHdvcmQocGFyYW1ldGVyLCBzdGFydCA9IDMsIHNlcCA9IGZpeGVkKCJfIikpLCAiX3RlbXAiLCBzZXAgPSAiIikpICU+JQogIGdncGxvdChhZXMoeCA9IGRhdGUsIHkgPSB0ZW1wLCBjb2xvdXIgPSBwYXJhbWV0ZXIpKSArCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDEpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoCiAgICAibWVhbl90ZW1wIiA9ICJvbGl2ZWRyYWIzIiwKICAgICJtZWRfdGVtcCIgPSAic2VhZ3JlZW4zIiwKICAgICJtYXhfdGVtcCIgPSAidG9tYXRvIiwKICAgICJtaW5fdGVtcCIgPSAiZG9kZ2VyYmx1ZSIsCiAgICAicmFuZ2VfdGVtcCIgPSAiZ29sZGVucm9kMyIsCiAgICAidmFyX3RlbXAiID0gImRhcmtnb2xkZW5yb2QxIgogICkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYXMuRGF0ZShjKCIyMDIzLTAxLTAxIiwgIjIwMjMtMDQtMDEiLCAiMjAyMy0wNy0wMSIpKSkgKwogIGdndGl0bGUoIkZvdXIgV2Vla3MiKSArCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgICAgIHggPSAiIikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDIwKSArCiAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCiMgCiMgCiMgIyMjIEVJR0hUIFdFRUtTCiMgZWlnaHRfd2Vla190ZW1wcyA9IGdldF9wcmVkaWN0b3JzKGRhaWx5X3ZhbHVlcyA9IGRhaWx5X3RlbXBfZGF0YSwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd190ZW1wID0gdGVtcF9kYXRhLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbl9kYXlzID0gNTYpCiMgCiMgZWlnaHRfd2Vla19wbG90ID0gZWlnaHRfd2Vla190ZW1wcyAlPiUgCiMgICBwaXZvdF9sb25nZXIoY29scyA9IGMoLWRhdGUpLAojICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInBhcmFtZXRlciIsIAojICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJ0ZW1wIikgJT4lIAojICAgZmlsdGVyKHBhcmFtZXRlciAlaW4lIGMoImZpZnR5LXNpeF9kYXlfbWVhbiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAiZmlmdHktc2l4X2RheV9tZWQiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgImZpZnR5LXNpeF9kYXlfbWF4IiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAiZmlmdHktc2l4X2RheV9taW4iLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICJmaWZ0eS1zaXhfZGF5X3ZhciIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAiZmlmdHktc2l4X2RheV9yYW5nZSIpKSAlPiUgCiMgICBtdXRhdGUocGFyYW1ldGVyID0gcGFzdGUod29yZChwYXJhbWV0ZXIsIHN0YXJ0ID0gMywgc2VwID0gZml4ZWQoIl8iKSksICJfdGVtcCIsIHNlcCA9ICIiKSkgJT4lIAojICAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IHRlbXAsIGNvbG91ciA9IHBhcmFtZXRlcikpICsgCiMgICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKyAKIyAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygKIyAgICAgIm1lYW5fdGVtcCIgPSAib2xpdmVkcmFiMyIsCiMgICAgICJtZWRfdGVtcCIgPSAic2VhZ3JlZW4zIiwKIyAgICAgIm1heF90ZW1wIiA9ICJ0b21hdG8iLCAgCiMgICAgICJtaW5fdGVtcCIgPSAiZG9kZ2VyYmx1ZSIsCiMgICAgICJyYW5nZV90ZW1wIiA9ICJnb2xkZW5yb2QzIiwKIyAgICAgInZhcl90ZW1wIiA9ICJkYXJrZ29sZGVucm9kMSIKIyAgICkpICsgCiMgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYXMuRGF0ZShjKCIyMDIzLTAxLTAxIiwgIjIwMjMtMDQtMDEiLCAiMjAyMy0wNy0wMSIpKSkgKyAKIyAgIGdndGl0bGUoIkVpZ2h0IFdlZWtzIikgKyAKIyAgIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsCiMgICAgICAgIHggPSAiIikgKyAKIyAgIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDIwKSArIAojICAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKIyAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMjcwLCBoanVzdCA9IDAsIHZqdXN0ID0gMC41KSkKIyAKZ2dhcnJhbmdlKGRhaWx5X3Bsb3QsIHdlZWtfcGxvdCwgZm91cl93ZWVrX3Bsb3QsIAogICAgICAgICAgY29tbW9uLmxlZ2VuZCA9IFQsIG5yb3cgPSAxLCBsZWdlbmQgPSAiYm90dG9tIikKYGBgCgpgYGB7ciBtaXNjLWNvcnItcGVyaW9kcywgaW5jbHVkZSA9IEZ9CiNUaGUgZGlmZmVyZW50IHRpbWUgcGVyaW9kcyBleGFtaW5lZCBieSB0aGlzIGNsaW1hdGUgZGF0YSBoaWdobGlnaHRzIHRoYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG1pbmltdW0gYW5kIG1heGltdW0gdGVtcGVyYXR1cmVzIGNoYW5nZXMgYmFzZWQgb24gdGhlIHdpbmRvdyBleGFtaW5lZC4gRm9yIGV4YW1wbGUsIG1pbmltdW0gYW5kIG1heGltdW0gdGVtcGVyYXR1cmVzIGV4cGVyaWVuY2VkIG92ZXIgd2Vla2x5IGludGVydmFscyBhcmUgY2xvc2VseSBsaW5rZWQsIHdoZXJlYXMgdGhlcmUgaXMgYSBkaXN0aW5jdCBzZWFzb25hbCBjeWNsZSBpbiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gbWluaW11bSBhbmQgbWF4aW11bSB0ZW1wZXJhdHVyZXMgZXhwZXJpZW5jZWQgb3ZlciBwZXJpb2RzIG9mIGZvdXIgd2Vla3MuIAoKb25lX3dlZWtfZG95X2RhdGEgPSB3ZWVrX3RlbXBzICU+JSAKICBtdXRhdGUoZG95ID0geWRheShkYXRlKSkKCm9uZV93ZWVrX3RlbXBfY2lyY2xlID0gZ2dwbG90KG9uZV93ZWVrX2RveV9kYXRhLCBhZXMoeCA9IHNldmVuX2RheV9tZWFuX21heCwgeSA9IHNldmVuX2RheV9tZWFuX21pbiwgY29sb3VyID0gZG95KSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnQyKAogICAgaGlnaCA9ICJkb2RnZXJibHVlNCIsCiAgICBtaWQgPSAiY29yYWwyIiwKICAgIGxvdyA9ICJkb2RnZXJibHVlNCIsCiAgICBtaWRwb2ludCA9IDE4Mi41KSArIAogIGxhYnMoeCA9ICJNYXguIFRlbXAuICjCsEMpIiwKICAgICAgIHkgPSAiTWluLiBUZW1wLiAowrBDKSIpICsgCiAgbGFicyh4ID0gIk1heC4gVGVtcC4gKMKwQykiLAogICAgICAgeSA9ICJNaW4uIFRlbXAuICjCsEMpIikgKyAKICBnZ3RpdGxlKCJPbmUgV2VlayIpICsgCiAgdGhlbWVfbWF0dCgpCgpmb3VyX3dlZWtfZG95X2RhdGEgPSBmb3VyX3dlZWtfdGVtcHMgJT4lIAogIG11dGF0ZShkb3kgPSB5ZGF5KGRhdGUpKQoKZm91cl93ZWVrX3RlbXBfY2lyY2xlID0gZ2dwbG90KGZvdXJfd2Vla19kb3lfZGF0YSwgYWVzKHggPSBgdHdlbnR5LWVpZ2h0X2RheV9tYXhgLCB5ID0gYHR3ZW50eS1laWdodF9kYXlfbWluYCwgY29sb3VyID0gZG95KSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnQyKAogICAgaGlnaCA9ICJkb2RnZXJibHVlNCIsCiAgICBtaWQgPSAiY29yYWwyIiwKICAgIGxvdyA9ICJkb2RnZXJibHVlNCIsCiAgICBtaWRwb2ludCA9IDE4Mi41KSArIAogIGxhYnMoeCA9ICJNYXguIFRlbXAuICjCsEMpIiwKICAgICAgIHkgPSAiTWluLiBUZW1wLiAowrBDKSIpICsgCiAgZ2d0aXRsZSgiRm91ciBXZWVrIikgKyAKICB0aGVtZV9tYXR0KCkKCmdnYXJyYW5nZShvbmVfd2Vla190ZW1wX2NpcmNsZSwgZm91cl93ZWVrX3RlbXBfY2lyY2xlLAogICAgICAgICAgY29tbW9uLmxlZ2VuZCA9IFQsIGxlZ2VuZCA9ICJib3R0b20iKQpgYGAKCk9yZ2FuaXNtcyBhcmUgdW5saWtlbHkgdG8gYWNjbGltYXRlIGluc3RhbnRhbmVvdXNseSB0byBjaGFuZ2VzIGluIHRlbXBlcmF0dXJlLiBUbyBleHBsb3JlIHRoZSBwb3RlbnRpYWwgdGVtcG9yYWwgd2luZG93IHRoZXNlIGNvcGVwb2RzIGFyZSByZXNwb25kaW5nIHRvLCB3ZSBleGFtaW5lZCB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiB0aGVybWFsIGxpbWl0cyBhbmQgc3VtbWFyaWVzIG9mIHRoZSB0aGVybWFsIGVudmlyb25tZW50IG92ZXIgZGlmZmVyZW50IHBlcmlvZHMgb2YgdGltZS4gRm9yIGVhY2ggc3BlY2llcyAoaW5jbHVzaXZlIG9mIGFsbCBzZXhlcyBhbmQgc3RhZ2VzKSwgd2UgZXhhbWluZWQgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gQ1RtYXggYW5kIG9uZSBvZiBuaW5lIHJlcHJlc2VudGF0aW9ucyBvZiB0aGUgdGhlcm1hbCBlbnZpcm9ubWVudCBjYWxjdWxhdGVkIGZvciBwZXJpb2RzIG9mIHRpbWUgZnJvbSAxIHRvIDYwIGRheXMgYmVmb3JlIGNvbGxlY3Rpb24uIFRoZXNlIHBhcmFtZXRlcnMgaW5jbHVkZSB0aGUgb3ZlcmFsbCBtYXhpbXVtLCBtaW5pbXVtLCBtZWRpYW4sIGFuZCBtZWFuIHRlbXBlcmF0dXJlIGZvciB0aGUgcGVyaW9kIG9mIHRpbWUsIHRoZSB0ZW1wZXJhdHVyZSByYW5nZSBhbmQgdmFyaWFuY2UgZHVyaW5nIHRoaXMgdGltZSwgYW5kIHRoZSBtZWFuIGRhaWx5IHRlbXBlcmF0dXJlIG1heGltdW0sIG1pbmltdW0sIGFuZCByYW5nZS4gV2UgYWxzbyBleGFtaW5lZCB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBDVG1heCBhbmQgdGhlIHRlbXBlcmF0dXJlIHJlY29yZGVkIGF0IHRoZSB0aW1lIG9mIGNvbGxlY3Rpb24uIAoKYGBge3IgZXN0aW1hdGluZy1wcmVkaWN0b3ItY29ycmVsYXRpb25zLCBpbmNsdWRlID0gRn0KI1dlIGNhbiBzZWUgdGhhdCwgaW4gZ2VuZXJhbCwgY29wZXBvZHMgYXJlIHJlc3BvbmRpbmcgdG8gcHJveGltYXRlIGN1ZXMgZnJvbSB0aGUgdGhlcm1hbCBlbnZpcm9ubWVudCwgd2l0aCBjb3JyZWxhdGlvbnMgZ2VuZXJhbGx5IGRyb3BwaW5nIG9mZiBzdWJzdGFudGlhbGx5IGFzIGFjY2xpbWF0aW9uIHdpbmRvdyBkdXJhdGlvbiBpbmNyZWFzZXMuIEFuIGV4Y2VwdGlvbiBpcyAqRXBpc2NodXJhIGxhY3VzdHJpcyosIHdoaWNoIGFwcGVhcnMgdG8gYmUgcmVzcG9uZGluZyB0byBtYXhpbXVtIHRlbXBlcmF0dXJlcyBleHBlcmllbmNlZCBvdmVyIGEgMjAgZGF5IHRpbWUgcGVyaW9kLiAKCiMjIyBQdWxsaW5nIHByZWRpY3RvcnMgYW5kIG1lYXN1cmluZyBjb3JyZWxhdGlvbnMgZm9yIG11Y2ggZmluZXIgdGltZXNjYWxlczsgMS01NiBkYXlzCgpudW1fY29sbHMgPSBmdWxsX2RhdGEgJT4lIAogIGZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICBzZWxlY3QoY29sbGVjdGlvbl9kYXRlLCBzcF9uYW1lKSAlPiUgIAogIGRpc3RpbmN0KCkgJT4lICAKICBjb3VudChzcF9uYW1lKSAlPiUgCiAgZmlsdGVyKG4gPj0gNSkKCmNvcnJfdmFscyA9IGRhdGEuZnJhbWUoKQoKZHVyX3ZhbHMgPSBjKDE6NTApCmZvcihpIGluIGR1cl92YWxzKXsKICAKICBkdXJhdGlvbl90ZW1wcyA9IGdldF9wcmVkaWN0b3JzKGRhaWx5X3ZhbHVlcyA9IGRhaWx5X3RlbXBfZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfdGVtcCA9IHNlbGVjdCh0ZW1wX2RhdGEsIC1ob3VyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuX2RheXMgPSBpKSAlPiUgCiAgICBmaWx0ZXIoZGF0ZSAlaW4lIGFzX2RhdGUodW5pcXVlKGZ1bGxfZGF0YSRjb2xsZWN0aW9uX2RhdGUpKSkKICAKICBjb3JyX2RhdGEgPSBmdWxsX2RhdGEgJT4lCiAgICBzZWxlY3Qoc3BfbmFtZSwgY29sbGVjdGlvbl9kYXRlLCBjb2xsZWN0aW9uX3RlbXAsIHNleCwgY3RtYXgpICU+JSAKICAgIGZpbHRlcihzcF9uYW1lICVpbiUgbnVtX2NvbGxzJHNwX25hbWUpICU+JSAKICAgICNmaWx0ZXIoc2V4ID09ICJmZW1hbGUiKSAlPiUgCiAgICBtdXRhdGUoY29sbGVjdGlvbl9kYXRlID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpKSAlPiUgCiAgICBpbm5lcl9qb2luKGR1cmF0aW9uX3RlbXBzLCBqb2luX2J5KGNvbGxlY3Rpb25fZGF0ZSA9PSBkYXRlKSkgJT4lIAogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKGNvbGxlY3Rpb25fdGVtcCwgY29udGFpbnMoImRheV8iKSksCiAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInZhbHVlIiwgCiAgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAicHJlZGljdG9yIikgJT4lICAKICAgIGdyb3VwX2J5KHNwX25hbWUsIHByZWRpY3RvcikgJT4lIAogICAgc3VtbWFyaXNlKGNvcnJlbGF0aW9uID0gY29yLnRlc3QoY3RtYXgsIHZhbHVlKSRlc3RpbWF0ZSwKICAgICAgICAgICAgICBwLnZhbHVlID0gY29yLnRlc3QoY3RtYXgsIHZhbHVlKSRwLnZhbHVlLAogICAgICAgICAgICAgIGNpX2xvdyA9IGNvci50ZXN0KGN0bWF4LCB2YWx1ZSkkY29uZi5pbnRbMV0sCiAgICAgICAgICAgICAgY2lfaGlnaCA9IGNvci50ZXN0KGN0bWF4LCB2YWx1ZSkkY29uZi5pbnRbMl0sCiAgICAgICAgICAgICAgLmdyb3VwcyA9ICJrZWVwIikgJT4lIAogICAgZmlsdGVyKHByZWRpY3RvciAhPSAiY29sbGVjdGlvbl90ZW1wIikgJT4lIAogICAgbXV0YXRlKHNpZyA9IGlmZWxzZShwLnZhbHVlIDwwLjA1LCAiU2lnLiIsICJOb24gU2lnLiIpKSAlPiUgCiAgICBzZXBhcmF0ZShwcmVkaWN0b3IsICJfZGF5XyIsIGludG8gPSBjKE5BLCAicGFyYW1ldGVyIikpICU+JSAKICAgIG11dGF0ZShkdXJhdGlvbiA9IGkpCiAgCiAgY29ycl92YWxzID0gYmluZF9yb3dzKGNvcnJfdmFscywgY29ycl9kYXRhKQp9Cgpjb2xsX2NvcnIgPSBmdWxsX2RhdGEgJT4lCiAgZmlsdGVyKHNwX25hbWUgJWluJSBudW1fY29sbHMkc3BfbmFtZSkgJT4lIAogIGZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICBncm91cF9ieShzcF9uYW1lKSAlPiUgCiAgc3VtbWFyaXNlKGNvcnJlbGF0aW9uID0gY29yLnRlc3QoY3RtYXgsIGNvbGxlY3Rpb25fdGVtcCkkZXN0aW1hdGUsCiAgICAgICAgICAgIHAudmFsdWUgPSBjb3IudGVzdChjdG1heCwgY29sbGVjdGlvbl90ZW1wKSRwLnZhbHVlLAogICAgICAgICAgICBjaV9sb3cgPSBjb3IudGVzdChjdG1heCwgY29sbGVjdGlvbl90ZW1wKSRjb25mLmludFsxXSwKICAgICAgICAgICAgY2lfaGlnaCA9IGNvci50ZXN0KGN0bWF4LCBjb2xsZWN0aW9uX3RlbXApJGNvbmYuaW50WzJdKSAlPiUgCiAgbXV0YXRlKHNpZyA9IGlmZWxzZShwLnZhbHVlIDwwLjA1LCAiU2lnLiIsICJOb24gU2lnLiIpKSAlPiUgCiAgbXV0YXRlKGR1cmF0aW9uID0gMCwKICAgICAgICAgcGFyYW1ldGVyID0gImNvbGxfdGVtcCIpCgpjb3JyX3ZhbHMgPSBjb3JyX3ZhbHMgJT4lICAKICBtdXRhdGUoZHVyYXRpb24gPSBhcy5udW1lcmljKGR1cmF0aW9uKSkgJT4lIAogIGJpbmRfcm93cyhjb2xsX2NvcnIpCgpgYGAKClNob3duIGJlbG93IGFyZSB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnRzIGZvciB0aGVzZSByZWxhdGlvbnNoaXBzLiBFYWNoIGZhY2V0IHNob3dzIHRoZSByZWxhdGlvbnNoaXAgZm9yIGEgZGlmZmVyZW50IHBhcmFtZXRlciwgcGxvdHRlZCBhZ2FpbnN0IHRoZSBkdXJhdGlvbiBvZiB0aGUgdGltZSBwZXJpb2QgYmVmb3JlIGNvbGxlY3Rpb24uIAoKYGBge3Igc3VwcC1maWctY29ycmVsYXRpb24tZHVyYXRpb25zLCBmaWcud2lkdGg9MTQsIGZpZy5oZWlnaHQ9OCwgaW5jbHVkZSA9IFR9CmNvcnJfdmFscyAlPiUgCiAgbXV0YXRlKHBhcmFtZXRlciA9IGZjdF9yZWxldmVsKHBhcmFtZXRlciwgYygibWluIiwgIm1heCIsICJyYW5nZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibWVhbiIsICJtZWQiLCAidmFyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtZWFuX21pbiIsICJtZWFuX21heCIsICJtZWFuX3JhbmdlIikpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZHVyYXRpb24sIHkgPSBjb3JyZWxhdGlvbiwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZmFjZXRfd3JhcCgufnBhcmFtZXRlcikgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDAuOSkgKyAKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMS41KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIGxhYnMoeCA9ICJEdXJhdGlvbiAoZGF5cykiLAogICAgICAgeSA9ICJDb3JyZWxhdGlvbiIsIAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKCkKYGBgCgpUaGlzIHRhYmxlIGNvbnRhaW5zIHRoZSB0b3AgdGhyZWUgZmFjdG9ycyBmb3IgZWFjaCBzcGVjaWVzIChiYXNlZCBvbiBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCkuCgpgYGB7ciBwcmVkaWN0b3ItY29ycmVsYXRpb25zLCBpbmNsdWRlID0gRn0KY29ycl92YWxzICU+JSAgCiAgZmlsdGVyKHNpZyA9PSAiU2lnLiIpICU+JSAKICBkcm9wX25hKGNvcnJlbGF0aW9uKSAlPiUgCiAgZ3JvdXBfYnkoc3BfbmFtZSkgJT4lCiAgYXJyYW5nZShkZXNjKGNvcnJlbGF0aW9uKSkgJT4lIAogIHNsaWNlX2hlYWQobiA9IDMpICU+JSAKICBzZWxlY3QoIlNwZWNpZXMiID0gc3BfbmFtZSwgIlByZWRpY3RvciIgPSBwYXJhbWV0ZXIsICJEdXJhdGlvbiIgPSBkdXJhdGlvbiwgIkNvcnJlbGF0aW9uIiA9IGNvcnJlbGF0aW9uLCAiUC1WYWx1ZSIgPSBwLnZhbHVlKSAlPiUgCiAga25pdHI6OmthYmxlKGFsaWduID0gImMiKQpgYGAKClNob3duIGhlcmUgaXMgYSBncmFwaGljYWwgc3VtbWFyeSBvZiB0aGUgZHVyYXRpb24gb2YgdGhlIGJlc3QgcHJlZGljdG9ycyBmb3IgZWFjaCBzcGVjaWVzLiBOb3RlIHRoYXQgZm9yIHRoZSB0d28gTGVwdG9kaWFwdG9taWRzLCBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlIGhhZCB0aGUgbGFyZ2VzdCBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBzbyBkdXJhdGlvbiBpcyB6ZXJvLiBUaGlzIHJlcHJlc2VudGF0aW9uIGhpZ2hsaWdodHMgdGhhdCB0aGVyZSBpcyB2YXJpYXRpb24gYWNyb3NzIHRoZSBjb21tdW5pdHkgbm90IG9ubHkgaW4gdGhlIHBvdGVudGlhbCBkcml2ZXIgKGUuZy4gbWluaW11bSB2cy4gbWF4aW11bSB0ZW1wZXJhdHVyZXMpIGJ1dCBhbHNvIGluIHRoZSBkdXJhdGlvbiBvZiB0aW1lLiBUaGlzIHZhcmlhdGlvbiBpcyBub3QgZ3JvdXBlZCBieSBzZWFzb24gKHRoZSB3aW50ZXIgYW5kIHN1bW1lciBjb21tdW5pdGllcyBib3RoIGhhdmUgcmVwcmVzZW50YXRpdmUgc3BlY2llcyBhcHBhcmVudGx5IHJlc3BvbmRpbmcgdG8gc2hvcnQgYW5kIGxvbmcgZHVyYXRpb25zKS4gCgpgYGB7ciBtYWluLWZpZy1hY2MtZHVyYXRpb25zfQpkdXJhdGlvbl9wbG90ID0gY29ycl92YWxzICU+JSAgCiAgZmlsdGVyKHNpZyA9PSAiU2lnLiIpICU+JSAKICBkcm9wX25hKGNvcnJlbGF0aW9uKSAlPiUgCiAgZ3JvdXBfYnkoc3BfbmFtZSkgJT4lCiAgYXJyYW5nZShkZXNjKGNvcnJlbGF0aW9uKSkgJT4lIAogIHNsaWNlX2hlYWQobiA9IDEpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIG11dGF0ZSgibnVtIiA9IHJvd19udW1iZXIoKSwgCiAgICAgICAgIHNwX25hbWUgPSBmY3RfcmVvcmRlcihzcF9uYW1lLCBkdXJhdGlvbiwgLmZ1biA9IG1lYW4sIC5kZXNjID0gVCkpICU+JSAKICBhcnJhbmdlKHNwX25hbWUpICU+JSAKICBzZWxlY3QoIlNwZWNpZXMiID0gc3BfbmFtZSwgIlByZWRpY3RvciIgPSBwYXJhbWV0ZXIsICJEdXJhdGlvbiIgPSBkdXJhdGlvbiwgIkNvcnJlbGF0aW9uIiA9IGNvcnJlbGF0aW9uLCBudW0pICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBTcGVjaWVzLCB5ID0gRHVyYXRpb24sIGZpbGwgPSBQcmVkaWN0b3IsIGdyb3VwID0gbnVtKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAwLjUsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjYpLAogICAgICAgICAgIGNvbG91ciA9ICJibGFjayIpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiY29sbF90ZW1wIiA9ICJibGFjayIsICJtYXgiID0gIndoaXRlIiwgIm1pbiIgPSAiZ3JleSIpKSArIAogIGxhYnMoeCA9ICIiLCAKICAgICAgIHkgPSAiRHVyYXRpb24gXG4oZGF5cykiKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCmBgYHtyIG1haW4tZmlnLWFjYy1jb3JyZWxhdGlvbnMsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTZ9CmNvcnJlbGF0aW9uX2NvZWZfcGxvdCA9IGNvcnJfdmFscyAlPiUgIAogIGZpbHRlcihzaWcgPT0gIlNpZy4iIHwgcGFyYW1ldGVyID09ICJjb2xsX3RlbXAiKSAlPiUgCiAgZHJvcF9uYShjb3JyZWxhdGlvbikgJT4lIAogIGdyb3VwX2J5KHNwX25hbWUpICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgPT0gImNvbGxfdGVtcCIgfCBjb3JyZWxhdGlvbiA9PSBtYXgoY29ycmVsYXRpb24pKSAlPiUgCiAgYXJyYW5nZShzcF9uYW1lLCBwYXJhbWV0ZXIpICU+JSAKICBtdXRhdGUoIm51bSIgPSByb3dfbnVtYmVyKCkpICU+JSAKICBzZWxlY3QoIlNwZWNpZXMiID0gc3BfbmFtZSwgIlByZWRpY3RvciIgPSBwYXJhbWV0ZXIsICJEdXJhdGlvbiIgPSBkdXJhdGlvbiwgIkNvcnJlbGF0aW9uIiA9IGNvcnJlbGF0aW9uLCBudW0pICU+JSAKICBtdXRhdGUoUHJlZGljdG9yID0gaWZfZWxzZShQcmVkaWN0b3IgPT0gImNvbGxfdGVtcCIsIFByZWRpY3RvciwgImJlc3QiKSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgbXV0YXRlKFNwZWNpZXMgPSBmY3RfcmVvcmRlcihTcGVjaWVzLCBEdXJhdGlvbiwgLmZ1biA9IG1heCwgLmRlc2MgPSBUKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IFNwZWNpZXMsIHkgPSBDb3JyZWxhdGlvbiwgZmlsbCA9IFByZWRpY3RvciwgZ3JvdXAgPSBudW0pKSArIAogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDAuNSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNiksCiAgICAgICAgICAgY29sb3VyID0gImJsYWNrIikgKyAKICBsYWJzKHkgPSAiQ29ycmVsYXRpb24gXG5Db2VmZmljaWVudCIsCiAgICAgICBmaWxsID0gIkNvcnJlbGF0ZSIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJjb2xsX3RlbXAiID0gImJsYWNrIiwgImJlc3QiID0gIndoaXRlIikpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGMoMCwgMSksIGxpbWl0cyA9IGMoMCwxKSkgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzAwLCBoanVzdCA9IDAsIHZqdXN0ID0gMC41KSkKCmdnYXJyYW5nZShkdXJhdGlvbl9wbG90LCBjb3JyZWxhdGlvbl9jb2VmX3Bsb3QsIG5yb3cgPSAyLCBsZWdlbmQgPSAicmlnaHQiLCAKICAgICAgICAgIGhlaWdodHMgPSBjKDAuNCwgMC42KSkKYGBgCgpgYGB7ciBtaXNjLWFjYy1kdXJhdGlvbi1wbG90LCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD00LCBpbmNsdWRlID0gRn0KIyBQaGVub3R5cGljIHZhcmlhdGlvbiAobGlrZSBhY2NsaW1hdGlvbiBvZiB0aGVybWFsIGxpbWl0cykgaXMgYSBwaHlzaW9sb2dpY2FsIHByb2Nlc3MuIGRlcGVuZGluZyBvbiB0aGUgbWVjaGFuaXN0aWMgdW5kZXJwaW5uaW5ncyAoY2hhbmdlcyBpbiBIU1AgZXhwcmVzc2lvbiwgZXRjLiksIHRoZSBhbW91bnQgb2YgdGltZSBpdCB0YWtlcyBmb3IgYW4gaW5kaXZpZHVhbCB0byBhY2NsaW1hdGUgbWF5IHZhcnkgYmFzZWQgb24gYm9keSBzaXplIChsYXJnZXIgc3BlY2llcywgbW9yZSBjZWxscywgbW9yZSB0aW1lIHJlcXVpcmVkIHRvIGFjY2xpbWF0ZSkuIFNob3duIGhlcmUgaXMgdGhlIGR1cmF0aW9uIG9mIHRoZSBlbnZpcm9ubWVudGFsIGFjY2xpbWF0aW9uIHdpbmRvdyB0aGUgY29wZXBvZHMgYXBwZWFyIHRvIGJlIHJlc3BvbmRpbmcgdG8uICAKCm1lYW5fc2l6ZXMgPSBmdWxsX2RhdGEgJT4lIAogIGZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICBncm91cF9ieShzcF9uYW1lKSAlPiUgIAogIHN1bW1hcmlzZShtZWFuX3NpemUgPSBtZWFuKHNpemUsIG5hLnJtID0gVCkpCgpjb3JyX3ZhbHMgJT4lIAogIGdyb3VwX2J5KHNwX25hbWUpICU+JSAKICBmaWx0ZXIoY29ycmVsYXRpb24gPT0gbWF4KGNvcnJlbGF0aW9uKSkgJT4lICAKICBpbm5lcl9qb2luKG1lYW5fc2l6ZXMsIGJ5ID0gInNwX25hbWUiKSAlPiUgCiAgc2VsZWN0KHNwX25hbWUsIGR1cmF0aW9uLCBtZWFuX3NpemUpICU+JSAgCiAgZ2dwbG90KGFlcyh4ID0gbWVhbl9zaXplLCB5ID0gZHVyYXRpb24pKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHNwX25hbWUpLCAKICAgICAgICAgICAgIHNpemUgPSA0KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIGxhYnMoeCA9ICJNZWFuIEZlbWFsZSBTaXplIChtbSkiLAogICAgICAgeSA9ICJBY2NsaW1hdGlvbiBEdXJhdGlvbiIsCiAgICAgICBjb2xvdXIgPSAiU3BlY2llcyIpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKYGBgCgojIyBUcmFpdCBWYXJpYXRpb24gCgpTaG93biBiZWxvdyBhcmUgdGhlIGNsdXRjaCBzaXplIGRpc3RyaWJ1dGlvbnMgZm9yIHRoZSB0aHJlZSBkaWFwdG9taWlkIHNwZWNpZXMsIHdoaWNoIHByb2R1Y2UgZWdnIHNhY3MgdGhhdCBhbGxvdyBmb3IgZWFzeSBxdWFudGlmaWNhdGlvbiBvZiBmZWN1bmRpdHkuIAoKYGBge3Igc3VwcC1maWctZmVjdW5kaXR5LWhpc3RvZ3JhbSwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9MTB9CmZ1bGxfZGF0YSAlPiUgIAogIGRyb3BfbmEoZmVjdW5kaXR5KSAlPiUgIAogIGdncGxvdChhZXMoeCA9IGZlY3VuZGl0eSwgZmlsbCA9IHNwX25hbWVfc3ViKSkgKyAKICBmYWNldF93cmFwKC5+c3BfbmFtZV9zdWIsIG5jb2wgPSAxKSArIAogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMikgKyAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgbGFicyh4ID0gIkZlY3VuZGl0eSAoIyBFZ2dzKSIpICsKICB0aGVtZV9tYXR0X2ZhY2V0cygpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKCk9uZSBvZiB0aGUgbWFpbiBhaW1zIG9mIHRoaXMgcHJvamVjdCBpcyB0byBleGFtaW5lIHRoZSBwYXR0ZXJucyBhbmQgcHJvY2Vzc2VzIGRyaXZpbmcgdmFyaWF0aW9uIGluIHVwcGVyIHRoZXJtYWwgbGltaXRzIGFjcm9zcyB0aGVzZSBzcGVjaWVzIG9mIGNvcGVwb2RzLiAKCiMjIyBWYXJpYXRpb24gd2l0aCB0ZW1wZXJhdHVyZSAKCldlIGV4cGVjdCBvbmUgb2YgdGhlIHByaW1hcnkgZHJpdmVycyBvZiBjb3BlcG9kIHRoZXJtYWwgbGltaXRzIHRvIGJlIHRlbXBlcmF0dXJlLCBhcyBpbmRpdmlkdWFscyBhY2NsaW1hdGUgdG8gc2Vhc29uYWwgY2hhbmdlcy4gU2hvd24gYmVsb3cgYXJlIHRoZSBzZWFzb25hbCBwYXR0ZXJucyBvZiB3aGVuIGNvcGVwb2RzIHdlcmUgaW5jbHVkZWQgaW4gQ1RtYXggbWVhc3VyZW1lbnRzIChhIHByb3h5IGZvciB0aGUgc2Vhc29uIG9mIG9jY3VycmVuY2UpLCBhbmQgdGhlcm1hbCBsaW1pdHMgZm9yIGVhY2ggc3BlY2llcyBwbG90dGVkIGFnYWluc3QgdGhlIHRlbXBlcmF0dXJlIGF0IHRoZSB0aW1lIG9mIGNvbGxlY3Rpb24uIFdlIGdlbmVyYWxseSBzZWUgYW4gaW5jcmVhc2UgaW4gdGhlcm1hbCBsaW1pdHMgd2l0aCBpbmNyZWFzaW5nIGNvbGxlY3Rpb24gdGVtcGVyYXR1cmUuCgpgYGB7ciBmaWcud2lkdGg9NywgZmlnLmhlaWdodD01fQpzcF9jdG1heF90ZW1wID0gZnVsbF9kYXRhICU+JSAKICBmaWx0ZXIoc3BfbmFtZSAhPSAiT3NwaHJhbnRpY3VtIGxhYnJvbmVjdHVtIikgJT4lIAogIG11dGF0ZShzcF9uYW1lID0gYXMuZmFjdG9yKHNwX25hbWUpLAogICAgICAgICBzcF9uYW1lID0gZmN0X3Jlb3JkZXIoc3BfbmFtZSwgY3RtYXgsIC5kZXNjID0gVCkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBjb2xsZWN0aW9uX3RlbXAsIHkgPSBjdG1heCwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZmFjZXRfd3JhcChzcF9uYW1lfi4pICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGLCBsaW5ld2lkdGggPSAxLjUsIGNvbG91ciA9ICJncmV5MzAiKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDIsIGFscGhhID0gMC40KSArIAogIGxhYnMoeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIiwgCiAgICAgICB5ID0gIkNUbWF4ICjCsEMpIikgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKYGBge3IgbWFpbi1maWctc3Atc3VtbWFyaWVzLCBmaWcud2lkdGg9MTQsIGZpZy5oZWlnaHQ9NX0KZ2dhcnJhbmdlKHNhbXBsZV9kYXRlc19wbG90LCBzcF9jdG1heF90ZW1wLCBucm93ID0gMSwgCiAgICAgICAgICBsYWJlbHMgPSAiQVVUTyIpCmBgYAoKVGhlIGludGVyYWN0aW9uIGJldHdlZW4gc2Vhc29uYWwgY2hhbmdlcyBpbiB0ZW1wZXJhdHVyZSBhbmQgdGhlIGFjY2xpbWF0aW9uIG9mIHRoZXJtYWwgbGltaXRzIGxpa2VseSBhZmZlY3RzIHZ1bG5lcmFiaWxpdHkgb2YgZWFjaCBzcGVjaWVzIHRvIHdhcm1pbmcuIFNob3duIGJlbG93IGFyZSB3YXJtaW5nIHRvbGVyYW5jZSB2YWx1ZXMgZm9yIGVhY2ggc3BlY2llcywgY2FsY3VsYXRlZCBhcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGluZGl2aWR1YWwgQ1RtYXggYW5kIHRoZSB0ZW1wZXJhdHVyZSBhdCB0aGUgdGltZSBvZiBjb2xsZWN0aW9uLiBBbGwgc3BlY2llcyBtYWludGFpbmVkIHNvbWUgZGVncmVlIG9mIGJ1ZmZlciBiZXR3ZWVuIGVudmlyb25tZW50YWwgdGVtcGVyYXR1cmVzIGFuZCB1cHBlciB0aGVybWFsIGxpbWl0cywgYnV0ICpMLiBtaW51dHVzKiBhcHBlYXJzIHRvIGFwcHJvYWNoIGl0cyB1cHBlciB0aGVybWFsIGxpbWl0IGR1cmluZyB0aGUgd2FybWVzdCBjb2xsZWN0aW9ucyBkdXJpbmcgdGhlIHN1bW1lci4gCgpBbHNvIHNob3duIGJlbG93IGlzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBmZWN1bmRpdHkgKHRoZSBudW1iZXIgb2YgZWdncyBjb250YWluZWQgaW4gYSBjbHV0Y2gpIGZvciB0aGUgdGhyZWUgZGlhcHRvbWlkIHNwZWNpZXMuIEZvciB0aGUgdHdvIExlcHRvZGlhcHRvbXVzIHNwZWNpZXMsIHRoZXJlIGlzIG5vIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGNsdXRjaCBzaXplIGFuZCB0ZW1wZXJhdHVyZSwgd2hpbGUgdGhlcmUgYXBwZWFycyB0byBiZSBhIGdlbmVyYWwgaW5jcmVhc2UgaW4gY2x1dGNoIHNpemUgd2l0aCB0ZW1wZXJhdHVyZSBpbiB0aGUgU2tpc3RvZGlhcHRvbXVzIHNwZWNpZXMuIAoKYGBge3IgbWFpbi1maWctdHJhaXQtY29sbC10ZW1wLXBsb3RzLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9N30KCnd0X3RlbXAgPSBmdWxsX2RhdGEgJT4lIAogIGZpbHRlcihzcF9uYW1lICE9ICJPc3BocmFudGljdW0gbGFicm9uZWN0dW0iKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gY29sbGVjdGlvbl90ZW1wLCB5ID0gd2FybWluZ190b2wsIGNvbG91ciA9IHNwX25hbWUpKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDMsCiAgICAgICAgICAgICBhbHBoYSA9IDAuMykgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBsaW5ld2lkdGggPSAzKSArCiAgbGFicyh4ID0gIkNvbGxlY3Rpb24gVGVtcGVyYXR1cmUgKMKwQykiLCAKICAgICAgIHkgPSAiV2FybWluZyBUb2xlcmFuY2UgKMKwQykiLAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSAgKyAKICB5bGltKDAsMzApICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKZWdnc190ZW1wID0gZnVsbF9kYXRhICU+JSAKICBmaWx0ZXIoc3BfbmFtZSAhPSAiT3NwaHJhbnRpY3VtIGxhYnJvbmVjdHVtIikgJT4lIAogIGdncGxvdChhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IGZlY3VuZGl0eSwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMywKICAgICAgICAgICAgIGFscGhhID0gMC4zKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGxpbmV3aWR0aCA9IDMpICsKICBsYWJzKHggPSAiQ29sbGVjdGlvbiBUZW1wZXJhdHVyZSAowrBDKSIsIAogICAgICAgeSA9ICJGZWN1bmRpdHkgKCMgRWdncykiLAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSAgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKZ2dhcnJhbmdlKHd0X3RlbXAsIGVnZ3NfdGVtcCwgCiAgICAgICAgICBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gInJpZ2h0IikKYGBgCgpgYGB7ciBzdXBwLWZpZy1sc2ljLW1vcnBocywgaW5jbHVkZSA9IEZ9Cm1vcnBoX2RhdGEgPSBmdWxsX2RhdGEgJT4lIAogIGZpbHRlcihzZXggPT0gImZlbWFsZSIgJiBzcGVjaWVzID09ICJsZXB0b2RpYXB0b211c19zaWNpbGlzIikgJT4lICBtdXRhdGUoc3BfbmFtZSA9IGNhc2Vfd2hlbigKICAgIHNwX25hbWUgPT0gIkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMiICYgc2l6ZSA+PSAwLjg5IH4gIkxhcmdlIiwKICAgIHNwX25hbWUgPT0gIkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMiICYgc2l6ZSA8IDAuODkgfiAiU21hbGwiLAogICAgLmRlZmF1bHQgPSBzcF9uYW1lCiAgKSkKCmdncGxvdChtb3JwaF9kYXRhLCBhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IGN0bWF4LCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAyLCBhbHBoYSA9IDAuOCkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsIGxpbmV3aWR0aCA9IDIpICsgCiAgbGFicyh4ID0gIkNvbGxlY3Rpb24gVGVtcC4gKMKwQykiLCAKICAgICAgIHkgPSAiQ1RtYXggKMKwQykiKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgpgYGB7ciBtaXNjLWN0bWF4LXJhbmdlLXBsb3QsIGluY2x1ZGUgPSBGfQpmdWxsX2RhdGEgJT4lICAKICBmaWx0ZXIoc2V4ID09ICJmZW1hbGUiKSAlPiUgCiAgZ3JvdXBfYnkoc3BfbmFtZSwgY29sbGVjdGlvbl9kYXRlLCBjb2xsZWN0aW9uX3RlbXApICU+JSAgCiAgc3VtbWFyaXNlKCJjdG1heF9yYW5nZSIgPSBtYXgoY3RtYXgpIC0gbWluKGN0bWF4KSwKICAgICAgICAgICAgImN0bWF4X3ZhciIgPSB2YXIoY3RtYXgpLAogICAgICAgICAgICAic2FtcGxlX3NpemUiID0gbigpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBncm91cF9ieShzcF9uYW1lKSAlPiUgCiAgZmlsdGVyKHNwX25hbWUgIT0gIkxlcHRvZG9yYSBraW5kdGkiKSAlPiUgCiAgZmlsdGVyKHNhbXBsZV9zaXplID4gMykgJT4lIAogIGdncGxvdChhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IGN0bWF4X3ZhciwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZmFjZXRfd3JhcChzcF9uYW1lfi4pICsgCiAgZ2VvbV9wb2ludCgpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3VyID0gImJsYWNrIikgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpCmBgYAoKYGBge3IgY3RtYXgtY29sbC10ZW1wLW1vZGVsLCBpbmNsdWRlID0gRn0KIyBhZHVsdF9kYXRhID0gZnVsbF9kYXRhICU+JSAKIyAgIGZpbHRlcihzZXggPT0gImZlbWFsZSIpCgojIAojIGN0bWF4X3RlbXAubW9kZWwgPSBsbShkYXRhID0gbW9kZWxfZGF0YSwgY3RtYXggfiB0ZW1wX2NlbnQgKiBzcF9uYW1lKQojIHNpemVfdGVtcC5tb2RlbCA9IGxtKGRhdGEgPSBtb2RlbF9kYXRhLCBzaXplIH4gdGVtcF9jZW50ICogc3BfbmFtZSkKIyBmZWN1bmRfdGVtcC5tb2RlbCA9IGxtKGRhdGEgPSBkcm9wX25hKG1vZGVsX2RhdGEsIGZlY3VuZGl0eSksIGZlY3VuZGl0eSB+IHRlbXBfY2VudCAqIHNwX25hbWUpCiMgCiMgZmVjdW5kaXR5X3Jlc2lkcyA9IGNiaW5kKGRyb3BfbmEobW9kZWxfZGF0YSwgZmVjdW5kaXR5KSwgImZlY3VuZGl0eV9yZXNpZHMiID0gZmVjdW5kX3RlbXAubW9kZWwkcmVzaWR1YWxzKSAlPiUgCiMgICBzZWxlY3QoY29sbGVjdGlvbl9kYXRlLCBleHBfZGF0ZSwgcmVwbGljYXRlLCBzcGVjaWVzLCB0dWJlLCBmZWN1bmRpdHlfcmVzaWRzKQojIAojIGN0bWF4X3Jlc2lkcyA9IGNiaW5kKG1vZGVsX2RhdGEsICJyZXNpZHMiID0gY3RtYXhfdGVtcC5tb2RlbCRyZXNpZHVhbHMsICJzaXplX3Jlc2lkcyIgPSBzaXplX3RlbXAubW9kZWwkcmVzaWR1YWxzKSAlPiUgCiMgICBsZWZ0X2pvaW4oZmVjdW5kaXR5X3Jlc2lkcykKCmBgYAoKYGBge3Igc3VwcC1maWctY3RtYXgtdGltZS1pbi1sYWIsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD0xMH0KIyBDb3BlcG9kcyBzcGVudCBzZXZlcmFsIGRheXMgaW4gbGFiIGR1cmluZyBleHBlcmltZW50cy4gU2hvd24gYmVsb3cgYXJlIHRoZSBDVG1heCByZXNpZHVhbHMgKHRha2VuIGZyb20gYSBtb2RlbCBvZiBDVG1heCBhZ2FpbnN0IGNvbGxlY3Rpb24gdGVtcGVyYXR1cmUpIHBsb3R0ZWQgYWdhaW5zdCB0aGUgdGltZSBzcGVudCBpbiBsYWIgYmVmb3JlIG1lYXN1cmVtZW50cyB3ZXJlIG1hZGUuIEluZGl2aWR1YWwgcmVncmVzc2lvbnMgYXJlIHNob3duIGZvciB0aGUgcmVzaWR1YWxzIGFnYWluc3QgZGF5cyBpbiBsYWIgZm9yIGVhY2ggY29sbGVjdGlvbi4gV2UgY2FuIHNlZSBjbGVhcmx5IHRoYXQgdGhlcm1hbCBsaW1pdHMgYXJlIGZhaXJseSBzdGFibGUgb3ZlciB0aW1lLiAKCgojIGdncGxvdChjdG1heF9yZXNpZHMsIGFlcyh4ID0gZGF5c19pbl9sYWIsIHkgPSByZXNpZHMsIGNvbG91ciA9IHNwX25hbWUsIGdyb3VwID0gY29sbGVjdGlvbl9kYXRlKSkgKyAKIyAgIGZhY2V0X3dyYXAoc3BfbmFtZX4uKSArIAojICAgZ2VvbV9wb2ludChzaXplID0gNCwgYWxwaGEgPSAwLjUpICsgCiMgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYsIGxpbmV3aWR0aCA9IDEpICsgCiMgICAjc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoMDo1KSkgKyAKIyAgIGxhYnMoeCA9ICJEYXlzIGluIGxhYiIsIAojICAgICAgICB5ID0gIkNUbWF4IFJlc2lkdWFscyIpICsgCiMgICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKIyAgIHRoZW1lX21hdHRfZmFjZXRzKCkgKyAKIyAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgpgYGB7ciBzdXBwLWZpZy1tb2RlbC1wZXJmb3JtYW5jZSwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9MTN9Cgptb2RlbF9kYXRhID0gZnVsbF9kYXRhICU+JSAgCiAgZHJvcF9uYShzaXplLCBjdG1heCkgJT4lICAKICBmaWx0ZXIoc3BfbmFtZSAhPSAiT3NwaHJhbnRpY3VtIGxhYnJvbmVjdHVtIikgJT4lIAogIG11dGF0ZSh0ZW1wX2NlbnQgPSBzY2FsZShjb2xsZWN0aW9uX3RlbXAsIGNlbnRlciA9IFQsIHNjYWxlID0gRiksCiAgICAgICAgIHNpemVfY2VudCA9IHNjYWxlKHNpemUsIGNlbnRlciA9IFQsIHNjYWxlID0gRikpCgptaW5pbWFsLm1vZGVsID0gbG1lNDo6bG1lcihkYXRhID0gbW9kZWxfZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY3RtYXggfiBzcF9uYW1lICsgc2V4ICsgdGVtcF9jZW50ICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMXxkYXlzX2luX2xhYikpCgpmdWxsLm1vZGVsID0gbG1lNDo6bG1lcihkYXRhID0gZmlsdGVyKG1vZGVsX2RhdGEsIHNwX25hbWUgIT0gIk9zcGhyYW50aWN1bSBsYWJyb25lY3R1bSIpLAogICAgICAgICAgICAgICAgICAgICAgICBjdG1heCB+IHNwX25hbWUqc2V4KnRlbXBfY2VudCArCiAgICAgICAgICAgICAgICAgICAgICAgICAgKDF8ZGF5c19pbl9sYWIpKQoKZHJvcDEoZnVsbC5tb2RlbCwgdGVzdCA9ICJDaGlzcSIpCgpwZXJmb3JtYW5jZTo6dGVzdF9wZXJmb3JtYW5jZShtaW5pbWFsLm1vZGVsLCBmdWxsLm1vZGVsKQpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoZnVsbC5tb2RlbCkKCmNhcjo6QW5vdmEoZnVsbC5tb2RlbCwgdHlwZSA9ICJJSUkiKQoKc3BfY3RtYXggPSBlbW1lYW5zOjplbW1lYW5zKGZ1bGwubW9kZWwsIHNwZWNzID0gInNwX25hbWUiKSAlPiUgCiAgZGF0YS5mcmFtZSgpICU+JSAKICBzZWxlY3Qoc3BfbmFtZSwgInNwZWNpZXNfY3RtYXgiID0gZW1tZWFuKQoKbW9kZWxfY29lZnMgPSBlbW1lYW5zOjplbXRyZW5kcyhmdWxsLm1vZGVsLCB2YXIgPSAidGVtcF9jZW50Iiwgc3BlY3MgPSAic3BfbmFtZSIpICU+JSAKICBkYXRhLmZyYW1lKCkgJT4lIAogIGlubmVyX2pvaW4oc3BfY3RtYXgpIAoKY3RtYXhfcmVzaWRzID0gbW9kZWxfZGF0YSAlPiUgCiAgbXV0YXRlKHJlc2lkcyA9IHJlc2lkdWFscyhmdWxsLm1vZGVsKSkKYGBgCgpgYGB7ciBtYWluLWZpZy1BUlItc3ludGgtcGxvdCwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0KYXJyX2NvbWJpbmVkID0gc3ludGhfYXJyICU+JQogIGZpbHRlcihtZWFzdXJlID09ICJ1cHBlciIgJiBtZWFuX2xpbSA+IDIwKSAlPiUgCiAgc2VsZWN0KCJncm91cCIgPSBnZW51cywgYXJyLCBtZWFuX2xpbSkgJT4lIAogIG11dGF0ZSgiZGF0YXNldCIgPSAic3ludGhlc2lzIikgJT4lIAogIGJpbmRfcm93cygKICAgIHNlbGVjdChtb2RlbF9jb2VmcywgImdyb3VwIiA9IHNwX25hbWUsICdhcnInID0gdGVtcF9jZW50LnRyZW5kLCAnbWVhbl9saW0nID0gc3BlY2llc19jdG1heCkKICApICU+JSAKICBtdXRhdGUoZGF0YXNldCA9IGlmX2Vsc2UoaXMubmEoZGF0YXNldCksICJuZXcgZGF0YSIsICJzeW50aGVzaXMiKSwKICAgICAgICAgZ3JvdXAgPSBmY3RfcmVvcmRlcihncm91cCwgYXJyLCAuZGVzYyA9IFQpKQoKCmdncGxvdChhcnJfY29tYmluZWQsIGFlcyh4ID0gbWVhbl9saW0sIHkgPSBhcnIpKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwgCiAgICAgICAgICAgICAgbGluZXdpZHRoID0gMiwgY29sb3VyID0gImdyZXkzMCIpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gZmlsdGVyKGFycl9jb21iaW5lZCwgZGF0YXNldCAhPSAibmV3IGRhdGEiKSwgCiAgICAgICAgICAgICBzaXplID0gNCwgY29sb3VyID0gImdyZXkiKSArIAogIGdlb21fcG9pbnQoZGF0YSA9IGZpbHRlcihhcnJfY29tYmluZWQsIGRhdGFzZXQgPT0gIm5ldyBkYXRhIiksCiAgICAgICAgICAgICBhZXMoY29sb3VyID0gZ3JvdXApLCAKICAgICAgICAgICAgIHNpemUgPSA0KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIGxhYnMoeCA9ICJUaGVybWFsIExpbWl0IiwgCiAgICAgICB5ID0gIkFSUiIsIAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCmBgYAoKIyMjIFNleCBhbmQgc3RhZ2UgdmFyaWF0aW9uIGluIHRoZXJtYWwgbGltaXRzIApQcmV2aW91cyBzZWN0aW9ucyBoYXZlIGdlbmVyYWxseSBsdW1wZWQganV2ZW5pbGUsIGZlbWFsZSwgYW5kIG1hbGUgaW5kaXZpZHVhbHMgdG9nZXRoZXIuIFRoZXJlIG1heSBiZSBpbXBvcnRhbnQgc3RhZ2UtIG9yIHNleC1zcGVjaWZpYyBkaWZmZXJlbmNlcyBpbiBDVG1heCB0aG91Z2guIEZvciBhbGwgc3BlY2llcyBidXQgT3NwaHJhbnRpY3VtLCB3ZSBoYXZlIG1lYXN1cmVtZW50cyBmb3IgaW5kaXZpZHVhbHMgaW4gZGlmZmVyZW50IHN0YWdlcyBhbmQgb2YgZGlmZmVyZW50IHNleGVzLiAKCmBgYHtyIHNleC1zdGFnZS10YWJsZX0Kc2V4X3NhbXBsZV9zaXplcyA9IGZ1bGxfZGF0YSAlPiUgIAogIGdyb3VwX2J5KHNwX25hbWUsIHNleCkgJT4lICAKICBzdW1tYXJpc2UobnVtID0gbigpKSAlPiUgIAogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBzcF9uYW1lLAogICAgICAgICAgICAgIG5hbWVzX2Zyb20gPSBzZXgsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gbnVtLAogICAgICAgICAgICAgIHZhbHVlc19maWxsID0gMCkgJT4lIAogIHNlbGVjdCgiU3BlY2llcyIgPSBzcF9uYW1lLCAiSnV2ZW5pbGUiID0ganV2ZW5pbGUsICJGZW1hbGUiID0gZmVtYWxlLCAiTWFsZSIgPSBtYWxlKQoKa25pdHI6OmthYmxlKHNleF9zYW1wbGVfc2l6ZXMsIGFsaWduID0gImMiKQpgYGAKCkFjcm9zcyBncm91cCBjb21wYXJpc29ucyBzaG93IHRoYXQgdGhlcmUgYXJlIGdlbmVyYWxseSBubyBkaWZmZXJlbmNlcyBpbiB0aGVybWFsIGxpbWl0cyAocmVwcmVzZW50ZWQgaGVyZSBhcyB0aGUgcmVzaWR1YWxzIGZyb20gYSBDVG1heCB+IGNvbGxlY3Rpb25fdGVtcCB4IHNwZWNpZXMgbGluZWFyIHJlZ3Jlc3Npb24pLCB3aXRoIHRoZSBleGNlcHRpb24gb2YgU2VuZWNlbGxhIG1hbGVzLCB3aGljaCBtYXkgaGF2ZSBsb3dlciB0aGVybWFsIGxpbWl0cyAoYWx0aG91Z2ggc2FtcGxlIHNpemVzIGFyZSB2ZXJ5IHNtYWxsIGluIHRoaXMgZ3JvdXApLgoKYGBge3Igc3VwcC1maWctY3RtYXgtc2V4LCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9OH0KIyBjdG1heF9yZXNpZHMgJT4lIAojICAgZmlsdGVyKHNwX25hbWUgIT0gIk9zcGhyYW50aWN1bSBsYWJyb25lY3R1bSIpICU+JSAKIyAgIGdncGxvdChhZXMoeCA9IHNleCwgeSA9IHJlc2lkcywgY29sb3VyID0gc3BfbmFtZSkpICsgCiMgICBmYWNldF93cmFwKHNwX25hbWV+LikgKyAKIyAgIGdlb21faml0dGVyKHdpZHRoID0gMC4xLCBhbHBoYSA9IDAuNSkgKyAKIyAgIGdlb21fYm94cGxvdCh3aWR0aCA9IDAuNCwgZmlsbCA9IE5BLCBjb2xvdXIgPSAiYmxhY2siLCAKIyAgICAgICAgICAgICAgICBsaW5ld2lkdGggPSAxLCBvdXRsaWVyLmNvbG91ciA9IE5BKSArIAojICAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiMgICB0aGVtZV9tYXR0X2ZhY2V0cygpCmBgYAoKYGBge3IgdHJhaXQtdmFyaWFuY2UtY29sbC10ZW1wLCBpbmNsdWRlID0gRn0KIyAKIyBHaXZlbiB0aGUgbG9uZyBnZW5lcmF0aW9uIHRpbWVzIG9mIHRoZXNlIGNvcGVwb2RzLCBkZWNyZWFzZXMgaW4gdHJhaXQgdmFyaWFuY2UgbWF5IGluZGljYXRlIHNlbGVjdGlvbiBvdmVyIHRoZSBzZWFzb25hbCBjeWNsZS4gU2hvd24gYmVsb3cgYXJlIHRoZSB2YXJpYW5jZSBpbiBvYnNlcnZlZCBDVG1heCBhbmQgc2l6ZSwgcGxvdHRlZCBhZ2FpbnN0IGNvbGxlY3Rpb24gZGF0ZS4gVmFyaWFuY2UgZGVjcmVhc2VzIGluICpTa2lzdG9kaWFwdG9tdXMqLCBidXQgdGhpcyBwYXR0ZXJuIGlzIGRyaXZlbiBieSBhIHNpbmdsZSBjb2xsZWN0aW9uIHdpdGggaGlnaCB2YXJpYW5jZSBlYXJseSBpbiB0aGUgeWVhci4gU2l6ZSB2YXJpYW5jZSBpbmNyZWFzZXMgc2xpZ2h0bHkgaW4gKlNraXN0b2RpYXB0b211cyouIFZhcmlhbmNlIGluIGJvdGggQ1RtYXggYW5kIHNpemUgaXMgZmFpcmx5IGNvbnN0YW50IGluICpMZXB0b2RpYXB0b211cyBtaW51dHVzKiwgdGhlIG9ubHkgb3RoZXIgc3BlY2llcyBjb2xsZWN0ZWQgYWNyb3NzIHRoZSBlbnRpcmUgc2V0IG9mIHNhbXBsZXMgdGh1cyBmYXIuIAojIAojIGdncGxvdChkcm9wX25hKGFkdWx0X3N1bW1hcmllcywgY3RtYXhfdmFyKSwgYWVzKHggPSBhcy5EYXRlKGNvbGxlY3Rpb25fZGF0ZSksIHkgPSBjdG1heF92YXIsIGNvbG91ciA9IHNwX25hbWUpKSArIAojICAgZmFjZXRfd3JhcChzcF9uYW1lfi4sIHNjYWxlcyA9ICJmcmVlX3kiKSArIAojICAgZ2VvbV9wb2ludChzaXplID0gMikgKyAKIyAgIGdlb21fc21vb3RoKHNlID0gRikgKyAKIyAgIGxhYnMoeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIiwgCiMgICAgICAgIHkgPSAiQ1RtYXggVmFyaWFuY2UiKSArIAojICAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiMgICB0aGVtZV9tYXR0X2ZhY2V0cygpICsgCiMgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCiMgCiMgZ2dwbG90KGRyb3BfbmEoYWR1bHRfc3VtbWFyaWVzLCBzaXplX3ZhciksIGFlcyh4ID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpLCB5ID0gc2l6ZV92YXIsIGNvbG91ciA9IHNwX25hbWUpKSArIAojICAgZmFjZXRfd3JhcChzcF9uYW1lfi4pICsgCiMgICBnZW9tX3BvaW50KHNpemUgPSAyKSArIAojICAgZ2VvbV9zbW9vdGgoc2UgPSBGKSArIAojICAgbGFicyh4ID0gIkNvbGxlY3Rpb24gVGVtcC4gKMKwQykiLCAKIyAgICAgICAgeSA9ICJTaXplIFZhcmlhbmNlIikgKyAKIyAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAojICAgdGhlbWVfbWF0dF9mYWNldHMoKSArIAojICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKCmBgYHtyIHN1cHAtZmlnLW1vZGVsMi1wZXJmb3JtYW5jZSwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9MTN9Cm1vZGVsMl9kYXRhID0gbW9kZWxfZGF0YSAlPiUgCiAgZmlsdGVyKHNleCA9PSAiZmVtYWxlIiwgCiAgICAgICAgIHBhdGhvZ2VuICE9ICJ1bmNlcnRhaW4iLCAKICAgICAgICAgZGV2X2VnZ3MgIT0gInVuY2VydGFpbiIsIAogICAgICAgICBsaXBpZHMgIT0gInVuY2VydGFpbiIpICU+JSAKICBtdXRhdGUocGF0aG9nZW5zID0gZmN0X3JlbGV2ZWwocGF0aG9nZW4sICJubyIsICJzcG90IiwgImNsb3VkeSIsICJvdGhlciIpKQoKb3RoZXJfZmFjdG9yX21vZGVsID0gbG1lcihkYXRhID0gbW9kZWwyX2RhdGEsIAogICAgICAgICAgICAgICAgICAgICAgICAgIGN0bWF4fnNwX25hbWUgKiBjb2xsZWN0aW9uX3RlbXAgKyBkZXZfZWdncyArIHBhdGhvZ2VuICsgbGlwaWRzICsgKDF8ZGF5c19pbl9sYWIpKQoKZHJvcDEob3RoZXJfZmFjdG9yX21vZGVsLCBzY29wZSA9IH4uLCB0ZXN0ID0gIkNoaXNxIikKCnJlZHVjZWRfZmFjdG9yc19tb2RlbCA9IGxtZXIoZGF0YSA9IG1vZGVsMl9kYXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBjdG1heH5zcF9uYW1lICogY29sbGVjdGlvbl90ZW1wICsgcGF0aG9nZW4gKyAoMXxkYXlzX2luX2xhYikpCgpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwocmVkdWNlZF9mYWN0b3JzX21vZGVsKQpgYGAKCmBgYHtyIHN1cHAtZmlnLXBhdGhvZ2VuLWVmZmVjdCwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NX0KZW1tZWFuczo6ZW1tZWFucyhyZWR1Y2VkX2ZhY3RvcnNfbW9kZWwsIHNwZWMgPSAicGF0aG9nZW4iKSAlPiUgZW1tZWFuczo6Y29udHJhc3QobWV0aG9kPSJ0cnQudnMuY3RybCIscmVmPSJubyIpICU+JSBwbG90KCkgKyAKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwKSArIAogIGxhYnMoeCA9ICJEaWZmZXJlbmNlICjCsEMpIiwgCiAgICAgICB5ID0gIkNvbXBhcmlzb24iKSArIAogICAgdGhlbWVfbWF0dCgpCmBgYAoKCgojIyMgVHJhaXQgQ29ycmVsYXRpb25zIGFuZCBUcmFkZS1vZmZzCgpBIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHNpemUgYW5kIHVwcGVyIHRoZXJtYWwgbGltaXRzIGhhcyBiZWVuIHN1Z2dlc3RlZCBpbiBhIHdpZGUgcmFuZ2Ugb2Ygb3RoZXIgdGF4YS4gU2hvd24gYmVsb3cgYXJlIHRoZSBtZWFzdXJlZCB1cHBlciB0aGVybWFsIGxpbWl0cyBwbG90dGVkIGFnYWluc3QgcHJvc29tZSBsZW5ndGguIFRoZSBvdmVyYWxsIHJlbGF0aW9uc2hpcCAoaW5jbHVzaXZlIG9mIGFsbCBzcGVjaWVzKSBpcyBzaG93biBhcyB0aGUgYmxhY2sgbGluZSBpbiB0aGUgYmFja2dyb3VuZC4gUmVncmVzc2lvbnMgZm9yIGVhY2ggaW5kaXZpZHVhbCBzcGVjaWVzIGFyZSBhbHNvIHNob3duLiBBY3Jvc3MgdGhlIGVudGlyZSBhc3NlbWJsYWdlLCB0aGVyZSBpcyBhIHN0cm9uZyBkZWNyZWFzZSBpbiB0aGVybWFsIGxpbWl0cyB3aXRoIGluY3JlYXNpbmcgc2l6ZS4gIAoKYGBge3IgbWlzYy1jdG1heC1zaXplLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9N30KZnVsbF9kYXRhICU+JSAKICAjZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lICAKICBnZ3Bsb3QoIGFlcyh4ID0gc2l6ZSwgeSA9IGN0bWF4LCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAyLCBhbHBoYSA9IDAuMykgKyAKICBnZW9tX3Ntb290aChkYXRhID0gZnVsbF9kYXRhLCAKICAgICAgICAgICAgICBhZXMoeCA9IHNpemUsIHkgPSBjdG1heCksCiAgICAgICAgICAgICAgbWV0aG9kID0gImxtIiwgCiAgICAgICAgICAgICAgY29sb3VyID0iYmxhY2siLCAKICAgICAgICAgICAgICBsaW5ld2lkdGggPSAyLjUpICsgCiAgbGFicyh4ID0gIkxlbmd0aCAobW0pIiwgCiAgICAgICB5ID0gIkNUbWF4ICjCsEMpIiwKICAgICAgIGNvbG91ciA9ICJTcGVjaWVzIikgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKYGBgCgpTaG93biBoZXJlIGlzIHRoZSByZWxhdGlvbnNoaXAgZm9yIGVhY2ggc3BlY2llcyBpbmRpdmlkdWFsbHkuIAoKYGBge3IgbWlzYy1pbmQtc3AtY3RtYXgtc2l6ZSwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9Nn0KZnVsbF9kYXRhICU+JSAKICAjZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lICAKICBncm91cF9ieShzcF9uYW1lKSAlPiUgZmlsdGVyKG4oKSA+MikgJT4lIGZpbHRlcighc3RyX2RldGVjdChzcF9uYW1lLCBwYXR0ZXJuID0gImtpbmR0aSIpKSAlPiUgCiAgZ2dwbG90KCBhZXMoeCA9IHNpemUsIHkgPSBjdG1heCwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZmFjZXRfd3JhcChzcF9uYW1lfi4sIHNjYWxlcyA9ICJmcmVlIiwgbnJvdyA9IDIpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMiwgYWxwaGEgPSAwLjgpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGLCBsaW5ld2lkdGggPSAyKSArIAogIGxhYnMoeCA9ICJMZW5ndGggKG1tKSIsIAogICAgICAgeSA9ICJDVG1heCAowrBDKSIsCiAgICAgICBjb2xvdXIgPSAiU3BlY2llcyIpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKClNob3duIGJlbG93IGlzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBtZWFuIHNpemUgYW5kIG1lYW4gdGhlcm1hbCBsaW1pdHMgZm9yIGZlbWFsZXMgb2YgZWFjaCBzcGVjaWVzLiBXZSBzZWUgdGhhdCBsYXJnZXIgc3BlY2llcyB3aXRoaW4gdGhlIGNvbW11bml0eSB0ZW5kIHRvIGhhdmUgYSBsb3dlciB0aGVybWFsIGxpbWl0IHRoYW4gc21hbGxlciBzcGVjaWVzLiAKCmBgYHtyIG1haW4tZmlnLW1lYW4tY3RtYXgtbWVhbi1zaXplLXBsb3QsIGZpZy53aWR0aD05LCBmaWcuaGVpZ2h0PTV9CmZ1bGxfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoc3BfbmFtZSwgc2V4KSAlPiUgCiAgc3VtbWFyaXplKG1lYW5fY3RtYXggPSBtZWFuKGN0bWF4LCBuYS5ybSA9IFQpLAogICAgICAgICAgICBtZWFuX3NpemUgPSBtZWFuKHNpemUsIG5hLnJtID0gVCkpICU+JSAKICAjZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAogIGdncGxvdChhZXMoeCA9IG1lYW5fc2l6ZSwgeSA9IG1lYW5fY3RtYXgpKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwgbGluZXdpZHRoID0gMiwgY29sb3VyID0gImJsYWNrIikgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBzcF9uYW1lLCBzaGFwZSA9IHNleCksCiAgICAgICAgICAgICBzaXplID0gNSkgKyAKICBsYWJzKHggPSAiTGVuZ3RoIChtbSkiLCAKICAgICAgIHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCmBgYAoKYGBge3IgY3RtYXhyZXNpZHMtc2l6ZSwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTcsIGluY2x1ZGUgPSBGfQojIGN0bWF4X3Jlc2lkcyAlPiUgCiMgICAjZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAojICAgZ2dwbG90KGFlcyh4ID0gc2l6ZSwgeSA9IHJlc2lkcywgY29sb3VyID0gc3BfbmFtZSkpICsgCiMgICBmYWNldF93cmFwKHNwX25hbWV+LikgKyAKIyAgIGdlb21fcG9pbnQoc2l6ZSA9IDIpICsgCiMgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYsIGxpbmV3aWR0aCA9IDIpICsgCiMgICBsYWJzKHggPSAiTGVuZ3RoIChtbSkiLCAKIyAgICAgICAgeSA9ICJDVG1heCAowrBDKSIpICsgCiMgICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKIyAgIHRoZW1lX21hdHQoKSArIAojICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKClNob3duIGhlcmUgaXMgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGZlY3VuZGl0eSBhbmQgc2l6ZSwgc2hvd2luZyB0aGUgY2xhc3NpYyBwYXR0ZXJuIG9mIGluY3JlYXNpbmcgZWdnIHByb2R1Y3Rpb24gd2l0aCBpbmNyZWFzaW5nIHNpemUuIAoKYGBge3IgZmVjdW5kaXR5LXNpemV9CnNpemVfZmVjdW5kX3Bsb3QgPSBjdG1heF9yZXNpZHMgJT4lICAKICBkcm9wX25hKGZlY3VuZGl0eSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHNpemUsIHkgPSBmZWN1bmRpdHksIGNvbG91ciA9IHNwX25hbWUpKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwgbGluZXdpZHRoID0gMikgKyAKICBnZW9tX3BvaW50KHNpemUgPSAyLCBhbHBoYSA9IDAuNSkgKyAKICBsYWJzKHggPSAiUHJvc29tZSBsZW5ndGggKG1tKSIsIAogICAgICAgeSA9ICJGZWN1bmRpdHkgKCMgRWdncykiLAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCmBgYAoKSW5kaXZpZHVhbHMgbWF5IGFsc28gYWxsb2NhdGUgZW5lcmd5IHRvIGRpZmZlcmVudCBmaXRuZXNzIHJlbGF0ZWQgdHJhaXRzLCBwcmlvcml0aXppbmcgcmVwcm9kdWN0aXZlIG91dHB1dCBvdmVyIGVudmlyb25tZW50YWwgdG9sZXJhbmNlLCBmb3IgZXhhbXBsZS4gU2hvd24gYmVsb3cgaXMgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIENUbWF4IHJlc2lkdWFscyAoYWdhaW4sIGNvbnRyb2xsaW5nIGZvciB0aGUgZWZmZWN0cyBvZiBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlKSBhZ2FpbnN0IGZlY3VuZGl0eS4gV2UgY2FuIHNlZSBjbGVhcmx5IHRoYXQgaW5kaXZpZHVhbHMgd2l0aCBpbmNyZWFzZWQgZmVjdW5kaXR5IGFyZSBub3QgZGVjcmVhc2luZyB0aGVybWFsIGxpbWl0cywgc3VnZ2VzdGluZyB0aGF0IHRoZXJlIGlzIG5vIGVuZXJnZXRpYyB0cmFkZS1vZmYgYmV0d2VlbiB0aGVzZSB0cmFpdHMuIApgYGB7ciwgbWFpbi1maWctZmVjdW5kaXR5LXBsb3RzLCBmaWcud2lkdGg9OC41LCBmaWcuaGVpZ2h0PTEwfQpjdG1heF9mZWN1bmRfcGxvdCA9IGN0bWF4X3Jlc2lkcyAlPiUgIAogIGRyb3BfbmEoZmVjdW5kaXR5KSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gcmVzaWRzLCB5ID0gZmVjdW5kaXR5LCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYsIGxpbmV3aWR0aCA9IDIpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMiwgYWxwaGEgPSAwLjUpICsgCiAgbGFicyh4ID0gIkNUbWF4IFJlc2lkdWFscyAowrBDKSIsIAogICAgICAgeSA9ICJGZWN1bmRpdHkgKCMgRWdncykiLAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgpnZ2FycmFuZ2Uoc2l6ZV9mZWN1bmRfcGxvdCwgY3RtYXhfZmVjdW5kX3Bsb3QsIG5jb2wgPSAxLCBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gInJpZ2h0IikKYGBgCgpQcmV2aW91cyBzdHVkaWVzIGhhdmUgc2hvd24gdGhhdCB0aGUgbWFnbml0dWRlIG9mIHRoZSBzaXplLWZlY3VuZGl0eSBjb3JyZWxhdGlvbiBtYXkgYmUgZW52aXJvbm1lbnRhbGx5LWRlcGVuZGVudC4gVGhpcyBpcyBub3QgdmlzaWJsZSBpcyB0aGUgZGF0YSBmcm9tIHRoZXNlIGNvbGxlY3Rpb25zLiAKCmBgYHtyIHN1cHAtZmlnLWZlYy1zaXplLWNvcnItdnMtdGVtcCwgZmlnLndpZHRoID0gNCwgZmlnLmhlaWdodD0xMH0KY29ycl9kYXRhID0gZnVsbF9kYXRhICU+JSAKICBkcm9wX25hKGZlY3VuZGl0eSkgJT4lIAogIGZpbHRlcihzcF9uYW1lICVpbiUgYygiTGVwdG9kaWFwdG9tdXMgc2ljaWxpcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICJMZXB0b2RpYXB0b211cyBtaW51dHVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICJTa2lzdG9kaWFwdG9tdXMgc3AiKSkgJT4lICAKICBncm91cF9ieShjb2xsZWN0aW9uX2RhdGUsIGNvbGxlY3Rpb25fdGVtcCwgc3BfbmFtZSkgJT4lIAogIHN1bW1hcmlzZShzaXplX2ZlY19jb3JyID0gY29yKHNpemUsIGZlY3VuZGl0eSksCiAgICAgICAgICAgIG4gPSBuKCksCiAgICAgICAgICAgIG1lYW5fZmVjdW5kaXR5ID0gbWVhbihmZWN1bmRpdHkpKSAlPiUgCiAgZmlsdGVyKG4gPj0gMykgJT4lIAogIHVuZ3JvdXAoKSAlPiUgIAogIGdyb3VwX2J5KHNwX25hbWUpICU+JSAKICBtdXRhdGUodGVtcF9jZW50ID0gc2NhbGUoY29sbGVjdGlvbl90ZW1wLCBzY2FsZSA9IEYpKQoKZ2dwbG90KGNvcnJfZGF0YSwgYWVzKHggPSB0ZW1wX2NlbnQsIHkgPSBzaXplX2ZlY19jb3JyLCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBmYWNldF93cmFwKHNwX25hbWV+LiwgbnJvdyA9IDMpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgbGluZXdpZHRoID0gMikgKyAKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIGxhYnMoeCA9ICJUZW1wZXJhdHVyZSAoY2VudGVyZWQpIiwgCiAgICAgICB5ID0gIkNvcnJlbGF0aW9uIENvZWZmaWNpZW50IikgKyAKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTEsIDEpKSArCiAgdGhlbWVfbWF0dF9mYWNldHMoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCiMgZ2dwbG90KGNvcnJfZGF0YSwgYWVzKHggPSBzaXplX2ZlY19jb3JyKSkgKwojICAgICBmYWNldF93cmFwKHNwX25hbWV+LiwgbnJvdyA9IDMpICsKIyAgIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4yKQpgYGAKCgojIyBPdGhlciBwYXR0ZXJucyBpbiB2YXJpYXRpb24gCgoqTGVwdG9kaWFwdG9tdXMgc2ljaWxpcyogaXMgdGhlIG1vc3QgYWJ1bmRhbnQgc3BlY2llcyBkdXJpbmcgdGhlIHdpbnRlci4gVGhlcmUgd2FzIGEgbGFyZ2Ugc2hpZnQgaW4gdGhlIHNpemUgb2YgbWF0dXJlIGZlbWFsZXMgdG93YXJkcyB0aGUgZW5kIG9mIERlY2VtYmVyLiBUaGVzZSBsYXJnZSBhbmQgc21hbGwgaW5kaXZpZHVhbHMgYXJlIHRoZSBzYW1lIHNwZWNpZXMgKGNvbmZpcm1lZCB2aWEgQ09JIHNlcXVlbmNpbmcpLCBzdWdnZXN0aW5nIHRoaXMgc2hpZnQgbWF5IGluc3RlYWQgcmVmbGVjdCBhIHRyYW5zaXRpb24gZnJvbSBvbmUgZ2VuZXJhdGlvbiB0byBhbm90aGVyLiBUaGlzIHNpemUgZGlmZmVyZW5jZSBtYXkgYmUgY2F1c2VkIGJ5IGRpZmZlcmVuY2VzIGluIHRoZSBkZXZlbG9wbWVudGFsIGVudmlyb25tZW50cy4gRm9yIGV4YW1wbGUsIGluZGl2aWR1YWxzIGRldmVsb3BpbmcgaW4gSmFudWFyeSBncm93IHVwIGF0IHZlcnkgbG93IHRlbXBlcmF0dXJlcywgYW5kIHRoZXJlZm9yZSBtYXkgcmVhY2ggbGFyZ2VyIHNpemVzLiBUaGVzZSBpbmRpdmlkdWFscyBvdmVyLXN1bW1lciBpbiBkZWVwIHdhdGVycywgdGhlbiByZS1lbWVyZ2UgaW4gT2N0b2JlciBhbmQgcHJvZHVjZSBhIG5ldyBnZW5lcmF0aW9uLiBXYXRlciB0ZW1wZXJhdHVyZXMgYXJlIHN0aWxsIGZhaXJseSBoaWdoIHRocm91Z2ggTm92ZW1iZXIsIHdoaWNoIHJlc3VsdHMgaW4gYSBnZW5lcmF0aW9uIG9mIHNtYWxsZXIgaW5kaXZpZHVhbHMuIFRoZXNlIGluZGl2aWR1YWxzIG1hdHVyZSBpbiB0aW1lIHRvIHByb2R1Y2UgYSBuZXcgZ2VuZXJhdGlvbiBpbiBKYW51YXJ5LiAKCmBgYHtyIHN1cHAtZmlnLWxzaWMtbW9ycGgtc2l6ZSwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9OX0KZnVsbF9kYXRhICU+JSAgCiAgZmlsdGVyKHNwX25hbWUgPT0gIkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMiKSAlPiUgCiAgZmlsdGVyKHNleCAhPSAianV2ZW5pbGUiKSAlPiUgCiAgZ3JvdXBfYnkoY29sbGVjdGlvbl9kYXRlKSAlPiUgCiAgbXV0YXRlKHNpemVfY2VudGVyID0gc2NhbGUoc2l6ZSwgY2VudGVyID0gVCwgc2NhbGUgPSBGKSkgJT4lIAogIGdncGxvdChhZXMoeSA9IGZhY3Rvcihjb2xsZWN0aW9uX2RhdGUpLCB4ID0gc2l6ZSwgZmlsbCA9IGNvbGxlY3Rpb25fdGVtcCkpICsgCiAgZmFjZXRfd3JhcChzZXh+LikgKyAKICBnZW9tX2RlbnNpdHlfcmlkZ2VzKGJhbmR3aWR0aCA9IDAuMDQpICsgCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMC44OSkgKyAKICBsYWJzKHggPSAiU2l6ZSAobW0pIiwKICAgICAgIHkgPSAiRGF0ZSIsIAogICAgICAgZmlsbCA9ICJDb2xsLiBUZW1wLiAowrBDKSIpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpKQpgYGAKCkEgc2ltaWxhciwgYnV0IGxlc3MgZGlzdGluY3QgcGF0dGVybiBjYW4gYmUgb2JzZXJ2ZWQgaW4gTC4gbWludXR1cyBpbmRpdmlkdWFscyBhcyB3ZWxsLiAKYGBge3Igc3VwcC1maWctbG1pbi1tb3JwaC1zaXplLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD05fQpmdWxsX2RhdGEgJT4lICAKICBmaWx0ZXIoc3BfbmFtZSA9PSAiTGVwdG9kaWFwdG9tdXMgbWludXR1cyIpICU+JSAKICBmaWx0ZXIoc2V4ICE9ICJqdXZlbmlsZSIpICU+JSAKICBnZ3Bsb3QoYWVzKHkgPSBmYWN0b3IoY29sbGVjdGlvbl9kYXRlKSwgeCA9IHNpemUsIGZpbGwgPSBjb2xsZWN0aW9uX3RlbXApKSArIAogIGZhY2V0X3dyYXAoc2V4fi4pICsgCiAgZ2VvbV9kZW5zaXR5X3JpZGdlcyhiYW5kd2lkdGggPSAwLjA0KSArIAogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAuNjkpICsgCiAgbGFicyh4ID0gIlNpemUgKG1tKSIsCiAgICAgICB5ID0gIkRhdGUiLCAKICAgICAgIGZpbGwgPSAiQ29sbC4gVGVtcC4gKMKwQykiKSArIAogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLjUsMC45KSkgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikpCmBgYAoKIyMgRGlzdHJpYnV0aW9uIExhZyBOb24tTGluZWFyIE1vZGVsIChETE5NIGFwcHJvYWNoKSAKCkRpc3RyaWJ1dGVkIGxhZyBtb2RlbHMgZXhhbWluZSBhIHJlc3BvbnNlIHZhcmlhYmxlLCBtZWFzdXJlZCBhdCBtdWx0aXBsZSB0aW1lIHBvaW50cywgYXMgYSBmdW5jdGlvbiBvZiB0aGUgbGFnZ2VkIG9jY3VycmVuY2Ugb2Ygc29tZSBwcmVkaWN0b3IgdmFyaWFibGUgKHJlc3BvbnNlIHkgYXQgdGltZSB0IGFzIGEgZnVuY3Rpb24gb2YgcHJlZGljdG9yIHgodC1sYWcpLiBUaGlzIG1ldGhvZCB1dGlsaXplcyBhIGJpLWRpbWVuc2lvbmFsIGRvc2UtbGFnLXJlc3BvbnNlIGZ1bmN0aW9uLCB3aGljaCBlc3NlbnRpYWxseSBleGFtaW5lcyBub3Qgb25seSB0aGUgZG9zZSBlZmZlY3QsIGJ1dCB0aGUgZWZmZWN0IG9mIHRoZSB0aW1pbmcgb2YgdGhlIGRvc2UuIAoKCmBgYHtyIGNvbXBpbGluZ190ZW1wX2xhZ3N9CiMgUnVuIHRoaXMgY29kZSwgc2F2ZSB0aGUgcHJvZHVjdCwgYW5kIHRoZW4ganVzdCByZWFkIGluIHRoZSB0ZW1wIGxhZyBkYXRhIG9iamVjdC4gVGFrZXMgdG9vIGxvbmcgdG8gcnVuIGVhY2ggdGltZSB0aGlzIGRvY3VtZW50IGlzIGtuaXQuIAoKIyBsYWdfdGVtcHMgPSB0ZW1wX2RhdGEgJT4lCiMgICBncm91cF9ieShkYXRlLCBob3VyKSAlPiUKIyAgIHN1bW1hcml6ZSgibWVhbl90ZW1wIiA9IG1lYW4odGVtcCwgbmEucm0gPSBUKSkgJT4lCiMgICB1bmdyb3VwKCkgJT4lCiMgICBtdXRhdGUocG9pbnRfbnVtID0gcm93X251bWJlcigpKQojIAojIHVuaXFfZGF5cyA9IGxlbmd0aCh1bmlxdWUobGFnX3RlbXBzJGRhdGUpKQojIAojIGcgPSBnYW0obWVhbl90ZW1wIH4gcyhwb2ludF9udW0sIGJzPSJjciIsIGs9dW5pcV9kYXlzICsgMTApLAojICAgICBtZXRob2QgPSAiUkVNTCIsCiMgICAgIGRhdGEgPSBsYWdfdGVtcHMpCiMgCiMgcG9pbnRzID0gc2VxKDEsIG5yb3cobGFnX3RlbXBzKSwgbGVuZ3RoLm91dCA9IGxlbmd0aChsYWdfdGVtcHMkaG91cikpCiMgCiMgZGYucmVzID0gZGYucmVzaWR1YWwoZykKIyAKIyBwcmVkX3RlbXBzID0gcHJlZGljdChnLCBuZXdkYXRhID0gbGFnX3RlbXBzLCB0eXBlID0gInJlc3BvbnNlIiwgc2UuZml0ID0gVFJVRSkKIyAKIyBsYWdfdGVtcHMgPSBsYWdfdGVtcHMgJT4lCiMgICBtdXRhdGUodHJlbmRfVCA9IHByZWRfdGVtcHMkZml0LAojICAgICAgICAgIHRyZW5kX3NlID0gcHJlZF90ZW1wcyRzZS5maXQsCiMgICAgICAgICAgdGVtcF9kaWZmID0gbWVhbl90ZW1wIC0gdHJlbmRfVCkKIyAKIyB3cml0ZS5jc3YobGFnX3RlbXBzLCBmaWxlID0gIi4vT3V0cHV0L0RhdGEvbGFnX3RlbXBzLmNzdiIsIHJvdy5uYW1lcyA9IEYpCgpgYGAKCmBgYHtyIHN1cHAtZmlnLWRhaWx5LW1heC1jdG1heCwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9NH0gCgpkbG5tX2RhdGEgPSBmdWxsX2RhdGEgJT4lICAKICBmaWx0ZXIoc2V4ID09ICJmZW1hbGUiKSAlPiUgCiAgZmlsdGVyKHNwX25hbWUgJWluJSBjKAogICAgIkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMiLAogICAgIkxlcHRvZGlhcHRvbXVzIG1pbnV0dXMiLAogICAgIlNraXN0b2RpYXB0b211cyBzcCIKICApKSAlPiUgCiAgc2VsZWN0KGNvbGxlY3Rpb25fZGF0ZSwgY29sbGVjdGlvbl90ZW1wLCBzcF9uYW1lLCBjdG1heCkgJT4lIAogIGdyb3VwX2J5KGNvbGxlY3Rpb25fZGF0ZSwgY29sbGVjdGlvbl90ZW1wLCBzcF9uYW1lKSAlPiUgIAogIHN1bW1hcmlzZShtZWFuX2N0bWF4ID0gbWVhbihjdG1heCwgbmEucm0gPSBUKSwKICAgICAgICAgICAgc2FtcGxlID0gbigpKQoKdGVtcF9kYXRhICU+JSAKICBncm91cF9ieShkYXRlKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5fdGVtcCA9IG1lYW4odGVtcCksCiAgICAgICAgICAgIG1heF90ZW1wID0gbWF4KHRlbXAsIG5hLnJtID0gVCkpICU+JSAKICByaWdodF9qb2luKGRsbm1fZGF0YSwgYnkgPSBqb2luX2J5KCJkYXRlIiA9PSAiY29sbGVjdGlvbl9kYXRlIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBtYXhfdGVtcCwgeSA9IG1lYW5fY3RtYXgpKSArIAogIGZhY2V0X3dyYXAoLn5zcF9uYW1lKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJnYW0iKSArIAogIGdlb21fcG9pbnQoKSArIAogIGxhYnMoeCA9ICJNYXggRGFpbHkgVGVtcC4gKMKwQykiLAogICAgICAgeSA9ICJNZWFuIENUbWF4ICjCsEMpIikgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpICsgCiAgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikpCmBgYAoKYGBge3Igc3VwcC1maWctZGxubS1wbG90fQoKc3BfbGlzdCA9IHVuaXF1ZShkbG5tX2RhdGEkc3BfbmFtZSkKCmZvcihsYWdfc3BlY2llcyBpbiBzcF9saXN0KXsKICAKICBkbG5tX2RhdGFfc3AgPSBkbG5tX2RhdGEgJT4lIAogICAgZmlsdGVyKHNwX25hbWUgPT0gbGFnX3NwZWNpZXMpCiAgCiAgIyBXZSBuZWVkIHRvIGVzdGltYXRlIGEgbWF0cml4IG9mIGV4cG9zdXJlIGhpc3RvcmllcyBmb3IgZWFjaCBvYnNlcnZhdGlvbi4gVGhpcyBjb250YWlucyB0aGUgc2VyaWVzIG9mIGV4cG9zdXJlcyBhdCBlYWNoIGxhZyAobCkgZm9yIGVhY2ggb2YgdGhlIG4gb2JzZXJ2YXRpb25zLCBjb25zdHJhaW5lZCBiZXR3ZWVuIGwwIChtaW5pbXVtIGxhZykgYW5kIEwgKG1heCBsYWcpLiAKICAKICBkYXRlcyA9IGRsbm1fZGF0YV9zcCRjb2xsZWN0aW9uX2RhdGUgIyBGb3IgZWFjaCBvZiB0aGVzZSBkYXRlcywgbWFrZSBhIHZlY3RvciBvZiB0aGUgcGFzdCAzMCBkYXlzIChpbmNsdWRpbmcgdGhlIGRheSBvZiBjb2xsZWN0aW9uKS4gTk9URTogRG9uJ3QgdXNlICd1bmlxdWUnIGRhdGVzIGhlcmUgc2luY2Ugc29tZSBjb2xsZWN0aW9ucyBoYWQgbXVsdGlwbGUgc3BlY2llcwogIAogIGV4cF9oaXN0X3ogPSBkYXRhLmZyYW1lKCkKICBleHBfaGlzdF90cmVuZCA9IGRhdGEuZnJhbWUoKQogIAogIGZvcihkIGluIGRhdGVzKXsKICAgIAogICAgaGlzdG9yeSA9IGxhZ190ZW1wcyAlPiUgCiAgICAgIGZpbHRlcihkYXRlIDw9IGQgJiBkYXRlID4gZCAtIDEwKSAlPiUgCiAgICAgIGFycmFuZ2UoZGVzYyhkYXRlKSwgZGVzYyhob3VyKSkgJT4lIAogICAgICBtdXRhdGUobGFnID0gcm93X251bWJlcigpIC0gMSkgJT4lIAogICAgICBzZWxlY3QobGFnLCBtZWFuX3RlbXAsIHRlbXBfZGlmZikKICAgIAogICAgel92ZWMgPSBzY2FsZShoaXN0b3J5JG1lYW5fdGVtcClbLDFdCiAgICBuYW1lcyh6X3ZlYykgPSBoaXN0b3J5JGxhZwogICAgCiAgICB0cmVuZF92ZWMgPSBoaXN0b3J5JHRlbXBfZGlmZgogICAgbmFtZXModHJlbmRfdmVjKSA9IGhpc3RvcnkkbGFnCiAgICAKICAgIGV4cF9oaXN0X3ogPSBiaW5kX3Jvd3MoZXhwX2hpc3Rfeiwgel92ZWMpCiAgICBleHBfaGlzdF90cmVuZCA9IGJpbmRfcm93cyhleHBfaGlzdF90cmVuZCwgdHJlbmRfdmVjKQogICAgCiAgfQogIAogICNwcmludChtYXgoZXhwX2hpc3RfdHJlbmQsIG5hLnJtID0gVCkpCiAgCiAgIyBUaGUgY3Jvc3MtYmFzaXMgZnVuY3Rpb24gZnJvbSBkbG5tIHdpbGwgdXNlIHRoZSBjbGFzcyBvZiB0aGUgeCBwYXJhbWV0ZXIgdG8gZGV0ZXJtaW5lIHdoYXQgdG8gZG8uIEluIG91ciBjYXNlLCB3ZSBuZWVkIHRvIHByb3ZpZGUgaXQgd2l0aCB0aGUgbWF0cml4IG9mIGV4cG9zdXJlIGhpc3RvcmllcyBmb3IgcmVhY2ggb2JzZXJ2YXRpb24gKHJvdykgYW5kIGxhZyAoY29sdW1uKS4gCiAgCiAgY2JfdGVtcHMgPSBjcm9zc2Jhc2lzKGV4cF9oaXN0X3RyZW5kLCBsYWcgPSBjKDAsZGltKGV4cF9oaXN0X3RyZW5kKVsyXS0xKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3ZhciA9bGlzdChmdW49ImNyIixkZj0zKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIGFyZ2xhZz1saXN0KGZ1bj0iY3IiLGRmPTMsaW50ZXJjZXB0PVQpKQogIAogICNzdW1tYXJ5KGNiX3RlbXBzKQogIAogIHBlbmFsaXplZF9tYXQgPC0gY2JQZW4oY2JfdGVtcHMpCiAgCiAgI2ZpdHRpbmcgR0FNCiAgbGFnLmdhbSA9IGdhbShkYXRhID0gZGxubV9kYXRhX3NwLCAKICAgICAgICAgICAgICAgIG1lYW5fY3RtYXggfiBjb2xsZWN0aW9uX3RlbXAgKyBjYl90ZW1wcywgCiAgICAgICAgICAgICAgICBtZXRob2QgPSAiR0NWLkNwIiwKICAgICAgICAgICAgICAgIHBhcmFQZW49bGlzdChjYl90ZW1wcz1wZW5hbGl6ZWRfbWF0KSkKICAKICAjIHN1bW1hcnkobGFnLmdhbSkKICAjIEFJQyhsYWcuZ2FtKQogIAogICNlc3RpbWF0aW9uIG9mIGV4cG9zdXJlcyBlZmZlY3RzCiAgCiAgI2RlZmF1bHQgcGxvdHMKICBwcmVkX2dhbV9aczwtY3Jvc3NwcmVkKGNiX3RlbXBzLCBsYWcuZ2FtLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGN1bXVsPUYsIGNlbj0wLCBjaS5sZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICAgICAgICAgICBhdD1zZXEoLTQsNCwgMC4xKSkKICAKICBwbG90KHByZWRfZ2FtX1pzLCAiY29udG91ciIsIG1haW4gPSBsYWdfc3BlY2llcykKICAjIAogICMgcGxvdChwcmVkX2dhbV9acywgYm9yZGVyID0gMiwgY3VtdWw9RiwKICAjICAgICAgIHRoZXRhPTExMCxwaGk9MjAsbHRoZXRhPS04MCkKICAKICBwbG90KHByZWRfZ2FtX1pzLCAic2xpY2VzIiwKICAgICAgIHZhciA9IGMoMywtMyksCiAgICAgICBsYWcgPSBjKDEsMjAwKSwKICAgICAgIGNvbCA9IDIpCiAgCn0KCgpgYGAKCgojIyBIaW5kY2FzdGluZyB2dWxuZXJhYmlsaXR5IHdpdGggZGlmZmVyZW50IGFjY2xpbWF0aW9uIHNjZW5hcmlvcwpVc2luZyB0aGUgb2JzZXJ2ZWQgdGhlcm1hbCBsaW1pdCBkYXRhLCB3ZSBjYW4gcHJvZHVjZSBhIGhpbmRjYXN0IG9mIHRoZXJtYWwgc3RyZXNzIGZvciBMYWtlIENoYW1wbGFpbiBjb3BlcG9kcy4gRm9yIHRoZXNlIGluaXRpYWwgYXNzYXlzLCB3ZSB3aWxsIGRlZmluZSB0aGVybWFsIHN0cmVzcyBhcyBhbnkgdGltZSB3aGVuIG1heGltdW0gZGFpbHkgd2F0ZXIgdGVtcGVyYXR1cmUgaXMgd2l0aGluIDXCsEMgb2YgY29wZXBvZCBDVG1heCBvciBoaWdoZXIgKGkuZS4gd2FybWluZyB0b2xlcmFuY2UgaXMgbGVzcyB0aGFuIDXCsEMpLiBXZSB3aWxsIHVzZSB0aHJlZSBkaWZmZXJlbnQgc2NlbmFyaW9zOiAxKSBlYWNoIHNwZWNpZXMgaGFzIGEgdW5pcXVlIGJ1dCBmaXhlZCB0aGVybWFsIGxpbWl0IChhdmVyYWdlIG1lYXN1cmVkIENUbWF4KSwgMikgc3BlY2llcyBoYXZlIHVuaXF1ZSB0aGVybWFsIGxpbWl0cyBhbmQgYXJlIGFibGUgdG8gYWNjbGltYXRlIChjb25zdGFudCBBUlIgYWNyb3NzIGFsbCBzcGVjaWVzIHVzZWQgdG8gcHJlZGljdCBDVG1heCBiYXNlZCBvbiBhdmVyYWdlIGRhaWx5IHRlbXBlcmF0dXJlcyksIGFuZCAzKSBzcGVjaWVzIGhhdmUgdW5pcXVlIHRoZXJtYWwgbGltaXRzIGFuZCBzcGVjaWVzLXNwZWNpZmljIGFjY2xpbWF0aW9uIChDVG1heCBwcmVkaWN0ZWQgdXNpbmcgd2hpY2hldmVyIGVudmlyb25tZW50YWwgZmFjdG9yIGFuZCBkdXJhdGlvbiBpcyB0aGUgc3Ryb25nZXN0IGNhbmRpZGF0ZSBmb3IgZHJpdmluZyBhY2NsaW1hdGlvbiAtIGZyb20gdGhlIGNvcnJlbGF0aW9uIGFuYWx5c2lzKS4gSW4gYWxsIGNhc2VzLCBkYXRhIGlzIGZpbHRlcmVkIHRvIGp1c3QgdGhlcm1hbCBsaW1pdHMgb2YgYWR1bHQgZmVtYWxlcy4gCgojIyMgU2NlbmFyaW8gMQpgYGB7cn0KbWVhbl9jdG1heCA9IGZ1bGxfZGF0YSAlPiUgCiAgZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lICAKICBncm91cF9ieShzcF9uYW1lKSAlPiUgCiAgc3VtbWFyaXplKCJtZWFuX2N0bWF4IiA9IG1lYW4oY3RtYXgpKSAlPiUgCiAgYXJyYW5nZShtZWFuX2N0bWF4KQoKa25pdHI6OmthYmxlKG1lYW5fY3RtYXgpCmBgYAoKYGBge3J9CiMgIyBDb25zdHJ1Y3RzIHRoZSBVUkwgZm9yIHRoZSBmdWxsIHRlbXBlcmF0dXJlIGRhdGEgc2V0OyBSVU4gVEhJUyBPTkNFCiMgaGluZF91cmwgPSBjb25zdHJ1Y3ROV0lTVVJMKHNpdGVOdW1iZXJzID0gc2l0ZU51bWJlciwgcGFyYW1ldGVyQ2QgPSBwYXJhbWV0ZXJDZCwgc2VydmljZSA9ICJ1diIpCiMgCiMgaGluZF90ZW1wX2RhdGEgPSBpbXBvcnRXYXRlck1MMShoaW5kX3VybCwgYXNEYXRlVGltZSA9IFQpICU+JQojICAgbXV0YXRlKCJkYXRlIiA9IGFzLkRhdGUoZGF0ZVRpbWUpKSAlPiUKIyAgIHNlbGVjdChkYXRlLCAidGVtcCIgPSBYXzAwMDEwXzAwMDAwKQojIAojIHdyaXRlLnRhYmxlKHggPSBoaW5kX3RlbXBfZGF0YSwgZmlsZSA9ICJoaW5kY2FzdF90ZW1wcy5jc3YiLCByb3cubmFtZXMgPSBGLCBzZXAgPSAiLCIpCmBgYAoKYGBge3J9CiMgZ2dwbG90KGhpbmRfdGVtcF9kYXRhLCBhZXMoeCA9IGRhdGUsIHkgPSB0ZW1wKSkgKyAKIyAgIGdlb21fbGluZShsaW5ld2lkdGggPSAwLjEpICsgCiMgICBsYWJzKHggPSAiRGF0ZSIsIAojICAgICAgICB5ID0gIldhdGVyIFRlbXBlcmF0dXJlICjCsEMpIikgKwojICAgdGhlbWVfbWF0dCgpCmBgYAoKSW4gdGhlIHNpbXBsZXN0IHNjZW5hcmlvLCBzcGVjaWVzIHRoZXJtYWwgbGltaXRzIGFyZSBzdGF0aWMgdGhyb3VnaCB0aW1lLCByZXByZXNlbnRlZCBieSB0aGUgYXZlcmFnZSBDVG1heCBvZiBhZHVsdCBmZW1hbGUgY29wZXBvZHMuIEluIHRoaXMgc2NlbmFyaW8sIG9ubHkgdGhyZWUgb2YgdGhlIHNldmVuIG9ic2VydmVkIHNwZWNpZXMgYXJlIGV4cG9zZWQgdG8gdGhlcm1hbCBzdHJlc3MgKHRlbXBlcmF0dXJlcyB3aXRoaW4gNcKwQyBvZiBDVG1heCkuIFRlbXBlcmF0dXJlcyBhcHByb2FjaGVkIHRoZSB0aGVybWFsIGxpbWl0IG9mICpMZXB0b2RpYXB0b211cyBzaWNpbGlzKiBvbiBhIGhhbmRmdWwgb2YgZGF5cy4gQnkgY29udHJhc3QsICpTZW5lY2VsbGEgY2FsYW5vaWRlcyogYW5kICpMaW1ub2NhbGFudXMgbWFjcnVydXMqIHdlcmUgYm90aCBleHBvc2VkIHRvIHN1YnN0YW50aWFsIHRoZXJtYWwgc3RyZXNzIHRocm91Z2hvdXQgYSBsYXJnZSBwb3J0aW9uIG9mIHRoZSB5ZWFyLCBsaWtlbHkgZXhwbGFpbmluZyB3aHkgdGhlc2Ugc3BlY2llcyBhcmUgYWJzZW50IGZyb20gdGhlIGNvbW11bml0eSBmb3IgdGhlIHN1bW1lciBhbmQgZmFsbCBwZXJpb2RzLiAKCmBgYHtyIHN1cHAtZmlnLWhpbmQxX3NjZW5hcmlvLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NX0KaGluZDFfZGF0YSA9IGhpbmRfdGVtcF9kYXRhICU+JSAKICBncm91cF9ieShkYXRlKSAlPiUgCiAgc3VtbWFyaXplKCJkYWlseV9tYXgiID0gbWF4KHRlbXApLAogICAgICAgICAgICAiZGFpbHlfbWVhbiIgPSBtZWFuKHRlbXApLCkgJT4lIAogIGJpbmRfY29scyhwaXZvdF93aWRlcihtZWFuX2N0bWF4LCBuYW1lc19mcm9tID0gc3BfbmFtZSwgdmFsdWVzX2Zyb20gPSBtZWFuX2N0bWF4KSkgJT4lICAKICBwaXZvdF9sb25nZXIoY29scyA9IGMoLWRhdGUsIC1kYWlseV9tYXgsIC1kYWlseV9tZWFuKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAic3BlY2llcyIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAibWVhbl9jdG1heCIpICU+JSAgCiAgbXV0YXRlKGxpbV9kaWZmID0gbWVhbl9jdG1heCAtIGRhaWx5X21heCkgJT4lICAKICBtdXRhdGUoZG95ID0geWRheShkYXRlKSwKICAgICAgICAgIm1ldGhvZCIgPSAiTm9fYWNjbGltYXRpb24iKQoKaGluZF9kYWlseV90ZW1wX2RhdGEgPSBoaW5kX3RlbXBfZGF0YSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIGdyb3VwX2J5KGRhdGUpICU+JSAKICBzdW1tYXJpc2UobWVhbl90ZW1wID0gbWVhbih0ZW1wKSwKICAgICAgICAgICAgbWVkX3RlbXAgPSBtZWRpYW4odGVtcCksCiAgICAgICAgICAgIHZhcl90ZW1wID0gdmFyKHRlbXApLCAKICAgICAgICAgICAgbWluX3RlbXAgPSBtaW4odGVtcCksIAogICAgICAgICAgICBtYXhfdGVtcCA9IG1heCh0ZW1wKSkgJT4lIAogIG11dGF0ZSgicmFuZ2VfdGVtcCIgPSBtYXhfdGVtcCAtIG1pbl90ZW1wKQoKI3RhYmxlKGhpbmQxX2RhdGEkc3BlY2llcykKCmhpbmQxX2RhdGEgJT4lIAogIGZpbHRlcihsaW1fZGlmZiA8PSA1KSAlPiUgIAogIGdncGxvdChhZXMoeCA9IGRveSwgeSA9IGxpbV9kaWZmLCBjb2xvdXIgPSBzcGVjaWVzKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gNSwgCiAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleSIpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKwogIGdlb21fc21vb3RoKHNlID0gRikgKyAKICBsYWJzKHggPSAiRGF5IG9mIFllYXIiLCAKICAgICAgIHkgPSAiUHJlZGljdGVkIFdhcm1pbmcgVG9sZXJhbmNlIFxuKMKwQyBBYm92ZSBEYWlseSBNYXgpIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQpgYGAKCiMjIyBTY2VuYXJpbyAyCkluIHRoZSBzZWNvbmQgc2NlbmFyaW8sIHRoZXJtYWwgbGltaXRzIHZhcnkgd2l0aGluIGFuZCBiZXR3ZWVuIHNwZWNpZXMuIEEgc2ltcGxlIG1vZGVsIGlzIHVzZWQgdG8gcHJlZGljdCBzcGVjaWVzIHRoZXJtYWwgbGltaXRzIGJhc2VkIG9uIG1lYW4gZGFpbHkgdGVtcGVyYXR1cmUgKENUbWF4IGFzIGEgZnVuY3Rpb24gb2Ygc3BlY2llcyBhbmQgY29sbGVjdGlvbiB0ZW1wZXJhdHVyZSwgYnV0IHdpdGhvdXQgdGhlIGludGVyYWN0aW9uIGJldHdlZW4gdGhlc2UgdHdvIGZhY3RvcnMpLiBUaGVzZSBwcmVkaWN0ZWQgdGhlcm1hbCBsaW1pdHMgYXJlIHRoZW4gY29tcGFyZWQgYWdhaW5zdCB0aGUgbWF4aW11bSBkYWlseSB0ZW1wZXJhdHVyZSB0byBlc3RpbWF0ZSB0aGVybWFsIHN0cmVzcywgYXMgaW4gU2NlbmFyaW8gMS4gSW5jbHVkaW5nIHRoaXMgc2ltcGxlIGZvcm0gb2YgYWNjbGltYXRpb24gaW4gdGhlIG1vZGVsIHJlZHVjZWQgdGhlIGRlZ3JlZSBvZiB0aGVybWFsIHN0cmVzcyBmb3IgZWFjaCBzcGVjaWVzLCBlbGltaW5hdGluZyBpdCBlbnRpcmVseSBmb3IgKkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMqLiBOb3RlIHRoYXQgdGhlIG1hZ25pdHVkZSBvZiB0aGUgcHJlZGljdGVkIHN0cmVzcyBpcyAgbG93IGVub3VnaCB0aGF0IHJlbW92aW5nIHRoZSA1wrBDIGJ1ZmZlciBhcm91bmQgdGhlIHByZWRpY3RlZCB0aGVybWFsIGxpbWl0cyB3b3VsZCBhY3R1YWxseSBsaW1pdCBwcmVkaWN0ZWQgdGhlcm1hbCBzdHJlc3MgdG8ganVzdCBhIGZldyBkYXlzIGZvciAqU2VuZWNlbGxhIGNhbGFub2lkZXMqLiAKCmBgYHtyIHN1cHAtZmlnLWhpbmQyX3NjZW5hcmlvLCBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0xMH0KaGluZGNhc3RfbW9kZWwxID0gbG0oZGF0YSA9IGZpbHRlcihmdWxsX2RhdGEsIHNleCA9PSAiZmVtYWxlIiksCiAgICAgICAgICAgICAgICAgICAgIGN0bWF4IH4gY29sbGVjdGlvbl90ZW1wICsgc3BfbmFtZSkKCmhpbmQyX2RhdGEgPSBoaW5kX3RlbXBfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lIAogIHN1bW1hcml6ZSgiY29sbGVjdGlvbl90ZW1wIiA9IG1lYW4odGVtcCksCiAgICAgICAgICAgICJkYWlseV9tYXgiID0gbWF4KHRlbXApKSAlPiUgCiAgYmluZF9jb2xzKAogICAgcGl2b3Rfd2lkZXIobWVhbl9jdG1heCwgCiAgICAgICAgICAgICAgICBuYW1lc19mcm9tID0gc3BfbmFtZSwgCiAgICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IG1lYW5fY3RtYXgpKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKC1kYXRlLCAtZGFpbHlfbWF4LCAtY29sbGVjdGlvbl90ZW1wKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAic3BfbmFtZSIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAibWVhbl9jdG1heCIpICU+JSAKICBzZWxlY3QoLW1lYW5fY3RtYXgpICU+JSAKICBtdXRhdGUoInByZWRfY3RtYXgiID0gcHJlZGljdC5sbSAoaGluZGNhc3RfbW9kZWwxLCBuZXdkYXRhID0gLikpICU+JSAKICBzZWxlY3QoZGF0ZSwgImRhaWx5X21lYW4iID0gY29sbGVjdGlvbl90ZW1wLCBkYWlseV9tYXgsICJzcGVjaWVzIiA9IHNwX25hbWUsIHByZWRfY3RtYXgpICU+JSAKICBtdXRhdGUobGltX2RpZmYgPSBwcmVkX2N0bWF4IC0gZGFpbHlfbWF4KSAlPiUgCiAgI2ZpbHRlcihsaW1fZGlmZiA8PSAwKSAlPiUgIAogIG11dGF0ZShkb3kgPSB5ZGF5KGRhdGUpLAogICAgICAgICAibWV0aG9kIiA9ICJDb25zdGFudF9hY2NsaW1hdGlvbiIpCgojIGdncGxvdChoaW5kMl9kYXRhLCBhZXMoeCA9IGRhaWx5X21lYW4sIHkgPSBwcmVkX2N0bWF4LCBjb2xvdXIgPSBzcGVjaWVzKSkgKwojICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgCgojIHRhYmxlKGhpbmQyX2RhdGEkc3BlY2llcykKaGluZDJfZGF0YSAlPiUgIAogIGZpbHRlcihsaW1fZGlmZiA8PSA1KSAlPiUgIAogIGdncGxvdChhZXMoeCA9IGRveSwgeSA9IGxpbV9kaWZmLCBjb2xvdXIgPSBzcGVjaWVzKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gNSwgCiAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleSIpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKwogIGdlb21fc21vb3RoKCkgKyAKICBsYWJzKHggPSAiRGF5IG9mIFllYXIiLCAKICAgICAgIHkgPSAiUHJlZGljdGVkIFdhcm1pbmcgVG9sZXJhbmNlIFxuKMKwQyBBYm92ZSBEYWlseSBNYXgpIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQpgYGAKCiMjIyBTY2VuYXJpbyAzClRoZSBmaW5hbCBzY2VuYXJpbyBhbGxvd3MgdGhlIGVudmlyb25tZW50YWwgdmFyaWFibGUgdXNlZCB0byBwcmVkaWN0IENUbWF4IHRvIHZhcnkgYmV0d2VlbiBzcGVjaWVzLiBGb3Igc3BlY2llcyBvYnNlcnZlZCBpbiBmZXdlciB0aGFuIDUgY29sbGVjdGlvbnMsIHdlIHVzZSB0aGUgc2FtZSBhcHByb2FjaCBhcyBpbiBTY2VuYXJpbyAyLiBGb3Igc3BlY2llcyBvYnNlcnZlZCBpbiBtb3JlIHRoYW4gNSBjb2xsZWN0aW9ucywgaG93ZXZlciwgdGhlIGZhY3RvciB3aXRoIHRoZSBzdHJvbmdlc3QgY29ycmVsYXRpb24gd2l0aCBDVG1heCBpcyB1c2VkIHRvIHByZWRpY3QgdGhlcm1hbCBsaW1pdHMuIFRoZXNlIGZhY3RvcnMgYXJlIGluY2x1ZGVkIGJlbG93LgoKYGBge3J9CmhpbmRfcHJlZHMgPSBjb3JyX3ZhbHMgJT4lICAKICBmaWx0ZXIoc2lnID09ICJTaWcuIikgJT4lIAogIGRyb3BfbmEoY29ycmVsYXRpb24pICU+JSAKICBncm91cF9ieShzcF9uYW1lKSAlPiUKICBhcnJhbmdlKGRlc2MoY29ycmVsYXRpb24pKSAlPiUgCiAgc2xpY2VfaGVhZChuID0gMSkgJT4lIAogIHNlbGVjdCgiU3BlY2llcyIgPSBzcF9uYW1lLCAiUHJlZGljdG9yIiA9IHBhcmFtZXRlciwgIkR1cmF0aW9uIiA9IGR1cmF0aW9uLCAiQ29ycmVsYXRpb24iID0gY29ycmVsYXRpb24sICJQLVZhbHVlIiA9IHAudmFsdWUpCgprbml0cjo6a2FibGUoaGluZF9wcmVkcywgYWxpZ24gPSAiYyIpCmBgYAoKYGBge3J9CmhpbmQzX2RhdGEgPSBoaW5kMl9kYXRhICU+JSAjIENvbnRhaW5zIGRhdGEgZm9yIHNwZWNpZXMgdGhhdCB3b24ndCBjaGFuZ2UgZnJvbSBzY2VuYXJpbyAyCiAgZmlsdGVyKCEoc3BlY2llcyAlaW4lIGNvcnJfdmFscyRzcF9uYW1lKSkKCnByZWRzX3RvX3B1bGwgPSBoaW5kX3ByZWRzICU+JSAgCiAgc2VsZWN0KFNwZWNpZXMsIFByZWRpY3RvciwgRHVyYXRpb24pIAoKZm9yKGkgaW4gMTpsZW5ndGgocHJlZHNfdG9fcHVsbCRTcGVjaWVzKSl7CiAgCiAgZHVyYXRpb24gPSBwcmVkc190b19wdWxsJER1cmF0aW9uW2ldCiAgCiAgaWYoZHVyYXRpb24gPT0gMCl7ICNUaGUgcHJpb3IgZGF5IHRlbXBlcmF0dXJlIG1ldHJpY3Mgc2hvdWxkIGJlIHVzZWQKICAgIAogICAgcHJlZGljdG9ycyA9IGhpbmRfZGFpbHlfdGVtcF9kYXRhICU+JSAKICAgICAgbXV0YXRlKGRhdGUgPSBkYXRlKSAKICAgIAogICAgcGFyYW1ldGVyID0gIm1lYW5fdGVtcCIgI3VzaW5nIG1lYW4gdGVtcGVyYXR1cmUgYXMgYSBwcm94eSBmb3IgY29sbGVjdGlvbiB0ZW1wCiAgICAKICAgIG1vZGVsX2RhdGEgPSBmdWxsX2RhdGEgJT4lCiAgICAgIGZpbHRlcihzcF9uYW1lICVpbiUgcHJlZHNfdG9fcHVsbCRTcGVjaWVzW2ldKSAlPiUgCiAgICAgIGZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICAgICAgbXV0YXRlKGNvbGxlY3Rpb25fZGF0ZSA9IGFzX2RhdGUoY29sbGVjdGlvbl9kYXRlKSkgJT4lIAogICAgICBpbm5lcl9qb2luKHByZWRpY3RvcnMsIGpvaW5fYnkoY29sbGVjdGlvbl9kYXRlID09IGRhdGUpKSAlPiUgIAogICAgICBzZWxlY3QoY3RtYXgsIGNvbnRhaW5zKHBhcmFtZXRlcikpCiAgICAKICAgIGlmKGRpbShtb2RlbF9kYXRhKVsyXSA9PSAyKXsKICAgICAgaGluZC5tb2RlbCA9IGxtKGRhdGEgPSBtb2RlbF9kYXRhLCAKICAgICAgICAgICAgICAgICAgICAgIGN0bWF4IH4gLikKICAgICAgCiAgICAgIHNwX2RhdGEgPSBwcmVkaWN0b3JzICU+JSAKICAgICAgICBzZWxlY3QoZGF0ZSwgY29udGFpbnMocGFyYW1ldGVyKSkgJT4lIAogICAgICAgIG11dGF0ZShwcmVkX2N0bWF4ID0gcHJlZGljdChoaW5kLm1vZGVsLCBuZXdkYXRhID0gLikpICU+JSAgCiAgICAgICAgc2VsZWN0KGRhdGUsIHByZWRfY3RtYXgpICU+JSAKICAgICAgICBpbm5lcl9qb2luKGhpbmRfZGFpbHlfdGVtcF9kYXRhLCBieSA9IGMoImRhdGUiKSkgJT4lIAogICAgICAgIG11dGF0ZSgic3BlY2llcyIgPSBwcmVkc190b19wdWxsJFNwZWNpZXNbaV0sCiAgICAgICAgICAgICAgICJkb3kiID0geWRheShkYXRlKSwKICAgICAgICAgICAgICAgbGltX2RpZmYgPSBwcmVkX2N0bWF4IC0gbWF4X3RlbXApICU+JSAKICAgICAgICBzZWxlY3QoZGF0ZSwgZGFpbHlfbWVhbiA9IG1lYW5fdGVtcCwgZGFpbHlfbWF4ID0gbWF4X3RlbXAsIHNwZWNpZXMsIHByZWRfY3RtYXgsIGxpbV9kaWZmLCBkb3kpCiAgICAgIAogICAgICBoaW5kM19kYXRhID0gYmluZF9yb3dzKGhpbmQzX2RhdGEsIHNwX2RhdGEpCiAgICB9ZWxzZXsKICAgICAgcHJpbnQoYyh1bmlxdWUoc3BfZGF0YSRzcGVjaWVzKSwgIlRvbyBtYW55IGNvbHVtbnMgc2VsZWN0ZWQiKSkKICAgIH0KICAgIAogIH0KICAKICBpZihkdXJhdGlvbiA+IDApewogICAgI05laXRoZXIgdGhlIHByaW9yIGRheSBub3IgZGF5IG9mIG1ldHJpY3Mgc2hvdWxkIGJlIHVzZWQ7IHVzZSBkdXJhdGlvbiBhcyBuX2RheXMKICAgIAogICAgcHJlZGljdG9ycyA9IGdldF9wcmVkaWN0b3JzKGRhaWx5X3ZhbHVlcyA9IGhpbmRfZGFpbHlfdGVtcF9kYXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfdGVtcCA9IGhpbmRfdGVtcF9kYXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuX2RheXMgPSBkdXJhdGlvbikKICAgIAogICAgcGFyYW1ldGVyID0gcHJlZHNfdG9fcHVsbCRQcmVkaWN0b3JbaV0KICAgIAogICAgbW9kZWxfZGF0YSA9IGZ1bGxfZGF0YSAlPiUKICAgICAgZmlsdGVyKHNwX25hbWUgJWluJSBwcmVkc190b19wdWxsJFNwZWNpZXNbaV0pICU+JSAKICAgICAgZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAogICAgICBtdXRhdGUoY29sbGVjdGlvbl9kYXRlID0gYXNfZGF0ZShjb2xsZWN0aW9uX2RhdGUpKSAlPiUgCiAgICAgIGxlZnRfam9pbihwcmVkaWN0b3JzLCBqb2luX2J5KGNvbGxlY3Rpb25fZGF0ZSA9PSBkYXRlKSkgJT4lICAKICAgICAgc2VsZWN0KGN0bWF4LCBjb250YWlucyhwYXN0ZSgiZGF5XyIsIHBhcmFtZXRlciwgc2VwID0gIiIpKSkKICAgIAogICAgaWYoZGltKG1vZGVsX2RhdGEpWzJdID09IDIpewogICAgICBoaW5kLm1vZGVsID0gbG0oZGF0YSA9IG1vZGVsX2RhdGEsIAogICAgICAgICAgICAgICAgICAgICAgY3RtYXggfiAuKQogICAgICAKICAgICAgc3BfZGF0YSA9IHByZWRpY3RvcnMgJT4lIAogICAgICAgIHNlbGVjdChkYXRlLCBjb250YWlucyhwYXJhbWV0ZXIpKSAlPiUgCiAgICAgICAgbXV0YXRlKHByZWRfY3RtYXggPSBwcmVkaWN0KGhpbmQubW9kZWwsIG5ld2RhdGEgPSAuKSkgJT4lICAKICAgICAgICBzZWxlY3QoZGF0ZSwgcHJlZF9jdG1heCkgJT4lIAogICAgICAgIGlubmVyX2pvaW4oaGluZF9kYWlseV90ZW1wX2RhdGEsIGJ5ID0gYygiZGF0ZSIpKSAlPiUgCiAgICAgICAgbXV0YXRlKCJzcGVjaWVzIiA9IHByZWRzX3RvX3B1bGwkU3BlY2llc1tpXSwKICAgICAgICAgICAgICAgImRveSIgPSB5ZGF5KGRhdGUpLAogICAgICAgICAgICAgICBsaW1fZGlmZiA9IHByZWRfY3RtYXggLSBtYXhfdGVtcCkgJT4lIAogICAgICAgIHNlbGVjdChkYXRlLCBkYWlseV9tZWFuID0gbWVhbl90ZW1wLCBkYWlseV9tYXggPSBtYXhfdGVtcCwgc3BlY2llcywgcHJlZF9jdG1heCwgbGltX2RpZmYsIGRveSkKICAgICAgCiAgICAgIGhpbmQzX2RhdGEgPSBiaW5kX3Jvd3MoaGluZDNfZGF0YSwgc3BfZGF0YSkKICAgICAgCiAgICB9ZWxzZXsKICAgICAgcHJpbnQoYyh1bmlxdWUoc3BfZGF0YSRzcGVjaWVzKSwgIlRvbyBtYW55IGNvbHVtbnMgc2VsZWN0ZWQiKSkKICAgIH0KICAgIAogIH0KfQoKCmhpbmQzX2RhdGEgPSBoaW5kM19kYXRhICU+JSAKICBtdXRhdGUoIm1ldGhvZCIgPSAiVmFyaWFibGVfYWNjbGltYXRpb24iKQpgYGAKClRoaXMgdGhpcmQgYXBwcm9hY2ggZGlkIG5vdCBhZmZlY3QgdGhlIHByZWRpY3RlZCBwYXR0ZXJucyBpbiAqTGltbm9jYWxhbnVzKiBvciAqU2VuZWNlbGxhKiAobmVpdGhlciBzcGVjaWVzIGhhcyBiZWVuIG9ic2VydmVkIGluIGVub3VnaCBjb2xsZWN0aW9ucyB0byBlc3RpbWF0ZSB0aGUgZWZmZWN0cyBvZiBkaWZmZXJlbnQgZW52aXJvbm1lbnRhbCBmYWN0b3JzKS4gQ2hhbmdpbmcgdGhlIGFjY2xpbWF0aW9uIGFwcHJvYWNoIGRpZCBhZmZlY3QgcGF0dGVybnMgaW4gdGhlcm1hbCBsaW1pdHMgaW4gdGhlIG90aGVyIHNwZWNpZXMgdGhvdWdoLiBUaGUgZmlndXJlIGJlbG93IHNob3dzIGhvdyBwcmVkaWN0ZWQgd2FybWluZyB0b2xlcmFuY2UgdmFyaWVzIG92ZXIgdGhlIHllYXIgaW4gdGhlIHNldmVuIHNwZWNpZXMsIGJhc2VkIG9uIHRoZSB0aHJlZSBkaWZmZXJlbnQgcHJlZGljdGlvbiBtZXRob2RzLiBJbiBnZW5lcmFsLCBjb25zdGFudCB0aGVybWFsIGxpbWl0cyAodGhlICdubyBhY2NsaW1hdGlvbicgbWV0aG9kKSByZXN1bHRlZCBpbiBsYXJnZXIgd2FybWluZyB0b2xlcmFuY2UgZHVyaW5nIHRoZSB3aW50ZXIgYW5kIGxvd2VyIHdhcm1pbmcgdG9sZXJhbmNlIGR1cmluZyB0aGUgc3VtbWVyLCBhbHRob3VnaCB0aGlzIGVmZmVjdCB3YXMgc21hbGwgaW4gbW9zdCBzcGVjaWVzLiAgICAgCmBgYHtyIHN1cHAtZmlnLWhpbmRfY2FzdF9zdW1tYXJ5LCBmaWcud2lkdGg9MTMsIGZpZy5oZWlnaHQ9MTB9CnN5bnRoZXNpcyA9IGJpbmRfcm93cygKICBzZWxlY3QoaGluZDFfZGF0YSwgZGF0ZSwgZG95LCBkYWlseV9tZWFuLCBkYWlseV9tYXgsIHNwZWNpZXMsICJwcmVkX2N0bWF4IiA9IG1lYW5fY3RtYXgsIGxpbV9kaWZmLCBtZXRob2QpLAogIHNlbGVjdChoaW5kMl9kYXRhLCBkYXRlLCBkb3ksIGRhaWx5X21lYW4sIGRhaWx5X21heCwgIHNwZWNpZXMsIHByZWRfY3RtYXgsIGxpbV9kaWZmLCBtZXRob2QpLAogIHNlbGVjdChoaW5kM19kYXRhLCBkYXRlLCBkb3ksIGRhaWx5X21lYW4sIGRhaWx5X21heCwgIHNwZWNpZXMsIHByZWRfY3RtYXgsIGxpbV9kaWZmLCBtZXRob2QpKSAlPiUgCiAgbXV0YXRlKG1ldGhvZCA9IGZjdF9yZWxldmVsKG1ldGhvZCwgIk5vX2FjY2xpbWF0aW9uIiwgIkNvbnN0YW50X2FjY2xpbWF0aW9uIiwgIlZhcmlhYmxlX2FjY2xpbWF0aW9uIikpICU+JSAKICBmaWx0ZXIoIShzcGVjaWVzID09ICJPc3BocmFudGljdW0gbGFicm9uZWN0dW0iICYgbWV0aG9kID09ICJWYXJpYWJsZV9hY2NsaW1hdGlvbiIpKQoKY2xpbWF0b2xvZ3kgPSBzeW50aGVzaXMgJT4lIAogIGdyb3VwX2J5KHNwZWNpZXMsIGRveSwgbWV0aG9kKSAlPiUgIAogIHN1bW1hcmlzZSgibWVhbl9kaWZmIiA9IG1lYW4obGltX2RpZmYpLAogICAgICAgICAgICAibWluX2RpZmYiID0gbWluKGxpbV9kaWZmKSwKICAgICAgICAgICAgIm1heF9kaWZmIiA9IG1heChsaW1fZGlmZikpICU+JSAKICBtdXRhdGUobWV0aG9kID0gZmN0X3JlbGV2ZWwobWV0aG9kLCAiTm9fYWNjbGltYXRpb24iLCAiQ29uc3RhbnRfYWNjbGltYXRpb24iLCAiVmFyaWFibGVfYWNjbGltYXRpb24iKSkKCmFjY19lZmZlY3RzID0gc3ludGhlc2lzICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhkYXRlLCBzcGVjaWVzLCBkb3kpLCAKICAgICAgICAgICAgICBuYW1lc19mcm9tID0gbWV0aG9kLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IGxpbV9kaWZmKSAlPiUgIAogIG11dGF0ZSgiY29uc3RfYWNjX2VmZmVjdCIgPSBDb25zdGFudF9hY2NsaW1hdGlvbiAtIE5vX2FjY2xpbWF0aW9uLAogICAgICAgICAidmFyX2FjY19lZmZlY3QiID0gVmFyaWFibGVfYWNjbGltYXRpb24gLSBOb19hY2NsaW1hdGlvbikKCmdncGxvdChzeW50aGVzaXMsIGFlcyh4ID0gZG95LCB5ID0gbGltX2RpZmYsIGNvbG91ciA9IG1ldGhvZCkpICsgCiAgZmFjZXRfd3JhcChzcGVjaWVzfi4pICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSA1LCBjb2xvdXIgPSAiZ3JleSIpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMSkgKyAKICBsYWJzKHggPSAiRGF5IG9mIFllYXIiLCAKICAgICAgIHkgPSAiUHJlZGljdGVkIFdhcm1pbmcgVG9sZXJhbmNlICjCsEMgQWJvdmUgRGFpbHkgTWF4KSIpICsgCiAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGFscGhhID0gMSkpKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKGJhc2Vfc2l6ZSA9IDE4KSArIAogIHRoZW1lKHN0cmlwLnRleHQueC50b3AgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkKYGBgCgpgYGB7ciBzdXBwLWZpZy1hY2Nfc2NlbmFyaW9fZWZmZWN0cywgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9N30Kd3RfaGluZGNhc3Rfc3VtbWFyeSA9IHN5bnRoZXNpcyAlPiUgIAogIG11dGF0ZSgieWVhciIgPSB5ZWFyKGRhdGUpKSAlPiUgCiAgZ3JvdXBfYnkoc3BlY2llcywgeWVhciwgbWV0aG9kKSAlPiUgCiAgc3VtbWFyaXNlKCJtaW5fd3QiID0gbWluKGxpbV9kaWZmKSwKICAgICAgICAgICAgIm1heF93dCIgPSBtYXgobGltX2RpZmYpKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKG1pbl93dCwgbWF4X3d0KSwgCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIm1ldHJpYyIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAid3QiKSAlPiUgCiAgZ3JvdXBfYnkoc3BlY2llcywgbWV0aG9kLCBtZXRyaWMpICU+JSAKICBzdW1tYXJpc2UoIm1lYW5fd3QiID0gbWVhbih3dCkpCgp3dF9oaW5kY2FzdF9zdW1tYXJ5ICU+JSAKICBmaWx0ZXIobWV0cmljID09ICJtaW5fd3QiKSAlPiUgCmdncGxvdChhZXMoeCA9IG1ldGhvZCwgeSA9IG1lYW5fd3QsIGdyb3VwID0gc3BlY2llcywgY29sb3VyID0gc3BlY2llcykpICsgCiAgI2ZhY2V0X3dyYXAoLn5tZXRyaWMsIHNjYWxlcyA9ICJmcmVlX3kiKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gNSkgKyAKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMikgKyAKICBnZW9tX3BvaW50KHNpemUgPSAzKSArIAogIGxhYnMoeCA9ICJTY2VuYXJpbyIsIAogICAgICAgeSA9ICJNZWFuIFllYXJseSBNaW5pbXVtIFdUICjCsEMpIikgKyAKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKCkgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwMCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCmBgYAo=